blob: 6386d1b16a23b418b89b24d6cb7f3022336c68b1 [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 Roeck30846992013-06-24 22:21:59 -0700174#define NUM_REG_BEEP 5 /* Max number of beep registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700175
176/* Common and NCT6775 specific data */
177
178/* Voltage min/max registers for nr=7..14 are in bank 5 */
179
180static const u16 NCT6775_REG_IN_MAX[] = {
181 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
182 0x55c, 0x55e, 0x560, 0x562 };
183static const u16 NCT6775_REG_IN_MIN[] = {
184 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
185 0x55d, 0x55f, 0x561, 0x563 };
186static const u16 NCT6775_REG_IN[] = {
187 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
188};
189
190#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800191#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700192#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700193
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800194#define NCT6775_REG_FANDIV1 0x506
195#define NCT6775_REG_FANDIV2 0x507
196
Guenter Roeck47ece962012-12-04 07:59:32 -0800197#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
198
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700199static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
200
Guenter Roeck30846992013-06-24 22:21:59 -0700201/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700202
203static const s8 NCT6775_ALARM_BITS[] = {
204 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
205 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
206 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700207 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700208 -1, -1, -1, /* unused */
209 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
210 12, -1 }; /* intrusion0, intrusion1 */
211
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800212#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800213#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800214#define INTRUSION_ALARM_BASE 30
215
Guenter Roeck30846992013-06-24 22:21:59 -0700216static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
217
218/*
219 * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
220 * 30..31 intrusion
221 */
222static const s8 NCT6775_BEEP_BITS[] = {
223 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
224 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
225 21, /* global beep enable */
226 6, 7, 11, 28, -1, /* fan1..fan5 */
227 -1, -1, -1, /* unused */
228 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
229 12, -1 }; /* intrusion0, intrusion1 */
230
231#define BEEP_ENABLE_BASE 15
232
Guenter Roecka6bd5872012-12-04 03:13:34 -0800233static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
234static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
235
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800236/* DC or PWM output fan configuration */
237static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
238static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
239
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800240/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800241
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800242static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
243static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
244static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
245 0x103, 0x203, 0x303, 0x803, 0x903 };
246static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
247 0x104, 0x204, 0x304, 0x804, 0x904 };
248static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
249 0x105, 0x205, 0x305, 0x805, 0x905 };
250static const u16 NCT6775_REG_FAN_START_OUTPUT[]
251 = { 0x106, 0x206, 0x306, 0x806, 0x906 };
252static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
253static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
254
255static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
256 0x107, 0x207, 0x307, 0x807, 0x907 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800257static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
258static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
259
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800260static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
261static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800262static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700263static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800264
Guenter Roeckaa136e52012-12-04 03:26:05 -0800265static const u16 NCT6775_REG_TEMP[] = {
266 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
267
268static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
269 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
270static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
271 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
272static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
273 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
274
275static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
276 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
277
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800278static const u16 NCT6775_REG_TEMP_SEL[] = {
279 0x100, 0x200, 0x300, 0x800, 0x900 };
280
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800281static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
282 0x139, 0x239, 0x339, 0x839, 0x939 };
283static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
284 0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
285static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
286 0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
287static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
288 0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
289static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
290 0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
291
Guenter Roeckaa136e52012-12-04 03:26:05 -0800292static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
293
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800294static const u16 NCT6775_REG_AUTO_TEMP[] = {
295 0x121, 0x221, 0x321, 0x821, 0x921 };
296static const u16 NCT6775_REG_AUTO_PWM[] = {
297 0x127, 0x227, 0x327, 0x827, 0x927 };
298
299#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
300#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
301
302static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
303
304static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
305 0x135, 0x235, 0x335, 0x835, 0x935 };
306static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
307 0x138, 0x238, 0x338, 0x838, 0x938 };
308
Guenter Roeckaa136e52012-12-04 03:26:05 -0800309static const char *const nct6775_temp_label[] = {
310 "",
311 "SYSTIN",
312 "CPUTIN",
313 "AUXTIN",
314 "AMD SB-TSI",
315 "PECI Agent 0",
316 "PECI Agent 1",
317 "PECI Agent 2",
318 "PECI Agent 3",
319 "PECI Agent 4",
320 "PECI Agent 5",
321 "PECI Agent 6",
322 "PECI Agent 7",
323 "PCH_CHIP_CPU_MAX_TEMP",
324 "PCH_CHIP_TEMP",
325 "PCH_CPU_TEMP",
326 "PCH_MCH_TEMP",
327 "PCH_DIM0_TEMP",
328 "PCH_DIM1_TEMP",
329 "PCH_DIM2_TEMP",
330 "PCH_DIM3_TEMP"
331};
332
333static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
334 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
335
336static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
337 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
338 0xa07 };
339
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700340/* NCT6776 specific data */
341
342static const s8 NCT6776_ALARM_BITS[] = {
343 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
344 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
345 -1, /* unused */
346 6, 7, 11, 10, 23, /* fan1..fan5 */
347 -1, -1, -1, /* unused */
348 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
349 12, 9 }; /* intrusion0, intrusion1 */
350
Guenter Roeck30846992013-06-24 22:21:59 -0700351static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
352
353static const s8 NCT6776_BEEP_BITS[] = {
354 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
355 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
356 24, /* global beep enable */
357 25, 26, 27, 28, 29, /* fan1..fan5 */
358 -1, -1, -1, /* unused */
359 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
360 30, 31 }; /* intrusion0, intrusion1 */
361
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800362static const u16 NCT6776_REG_TOLERANCE_H[] = {
363 0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
364
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800365static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
366static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
367
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800368static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800369static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800370
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800371static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
372 0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
373
Guenter Roeckaa136e52012-12-04 03:26:05 -0800374static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
375 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
376
377static const char *const nct6776_temp_label[] = {
378 "",
379 "SYSTIN",
380 "CPUTIN",
381 "AUXTIN",
382 "SMBUSMASTER 0",
383 "SMBUSMASTER 1",
384 "SMBUSMASTER 2",
385 "SMBUSMASTER 3",
386 "SMBUSMASTER 4",
387 "SMBUSMASTER 5",
388 "SMBUSMASTER 6",
389 "SMBUSMASTER 7",
390 "PECI Agent 0",
391 "PECI Agent 1",
392 "PCH_CHIP_CPU_MAX_TEMP",
393 "PCH_CHIP_TEMP",
394 "PCH_CPU_TEMP",
395 "PCH_MCH_TEMP",
396 "PCH_DIM0_TEMP",
397 "PCH_DIM1_TEMP",
398 "PCH_DIM2_TEMP",
399 "PCH_DIM3_TEMP",
400 "BYTE_TEMP"
401};
402
403static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
404 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
405
406static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
407 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
408
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700409/* NCT6779 specific data */
410
411static const u16 NCT6779_REG_IN[] = {
412 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
413 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
414
415static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
416 0x459, 0x45A, 0x45B, 0x568 };
417
418static const s8 NCT6779_ALARM_BITS[] = {
419 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
420 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
421 -1, /* unused */
422 6, 7, 11, 10, 23, /* fan1..fan5 */
423 -1, -1, -1, /* unused */
424 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
425 12, 9 }; /* intrusion0, intrusion1 */
426
Guenter Roeck30846992013-06-24 22:21:59 -0700427static const s8 NCT6779_BEEP_BITS[] = {
428 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
429 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
430 24, /* global beep enable */
431 25, 26, 27, 28, 29, /* fan1..fan5 */
432 -1, -1, -1, /* unused */
433 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
434 30, 31 }; /* intrusion0, intrusion1 */
435
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800436static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800437static const u16 NCT6779_REG_FAN_PULSES[] = {
438 0x644, 0x645, 0x646, 0x647, 0x648 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800439
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800440static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
441 0x136, 0x236, 0x336, 0x836, 0x936 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700442#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800443static const u16 NCT6779_REG_CRITICAL_PWM[] = {
444 0x137, 0x237, 0x337, 0x837, 0x937 };
445
Guenter Roeckaa136e52012-12-04 03:26:05 -0800446static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
447static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
448 0x18, 0x152 };
449static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
450 0x3a, 0x153 };
451static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
452 0x39, 0x155 };
453
454static const u16 NCT6779_REG_TEMP_OFFSET[] = {
455 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
456
457static const char *const nct6779_temp_label[] = {
458 "",
459 "SYSTIN",
460 "CPUTIN",
461 "AUXTIN0",
462 "AUXTIN1",
463 "AUXTIN2",
464 "AUXTIN3",
465 "",
466 "SMBUSMASTER 0",
467 "SMBUSMASTER 1",
468 "SMBUSMASTER 2",
469 "SMBUSMASTER 3",
470 "SMBUSMASTER 4",
471 "SMBUSMASTER 5",
472 "SMBUSMASTER 6",
473 "SMBUSMASTER 7",
474 "PECI Agent 0",
475 "PECI Agent 1",
476 "PCH_CHIP_CPU_MAX_TEMP",
477 "PCH_CHIP_TEMP",
478 "PCH_CPU_TEMP",
479 "PCH_MCH_TEMP",
480 "PCH_DIM0_TEMP",
481 "PCH_DIM1_TEMP",
482 "PCH_DIM2_TEMP",
483 "PCH_DIM3_TEMP",
484 "BYTE_TEMP"
485};
486
487static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
488 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
489 0, 0, 0, 0, 0, 0, 0, 0,
490 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
491 0x408, 0 };
492
493static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
494 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
495
Guenter Roeck6c009502012-07-01 08:23:15 -0700496/* NCT6102D/NCT6106D specific data */
497
498#define NCT6106_REG_VBAT 0x318
499#define NCT6106_REG_DIODE 0x319
500#define NCT6106_DIODE_MASK 0x01
501
502static const u16 NCT6106_REG_IN_MAX[] = {
503 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
504static const u16 NCT6106_REG_IN_MIN[] = {
505 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
506static const u16 NCT6106_REG_IN[] = {
507 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
508
509static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
510static const u16 NCT6106_REG_TEMP_HYST[] = {
511 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
512static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700513 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
514static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
515 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
516static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
517 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700518static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
519static const u16 NCT6106_REG_TEMP_CONFIG[] = {
520 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
521
522static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
523static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
524static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
525static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
526
527static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
528static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
529static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
530static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
531static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
532static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
533static const u16 NCT6106_REG_TEMP_SOURCE[] = {
534 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
535
536static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
537static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
538 0x11b, 0x12b, 0x13b };
539
540static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
541#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
542static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
543
544static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
545static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
546static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
547static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
548static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
549static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
550
551static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
552
553static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
554static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
555static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
556static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
557static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
558static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
559
560static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
561static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
562
563static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
564 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
565
566static const s8 NCT6106_ALARM_BITS[] = {
567 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
568 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
569 -1, /* unused */
570 32, 33, 34, -1, -1, /* fan1..fan5 */
571 -1, -1, -1, /* unused */
572 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
573 48, -1 /* intrusion0, intrusion1 */
574};
575
Guenter Roeck30846992013-06-24 22:21:59 -0700576static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
577 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
578
579static const s8 NCT6106_BEEP_BITS[] = {
580 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
581 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
582 32, /* global beep enable */
583 24, 25, 26, 27, 28, /* fan1..fan5 */
584 -1, -1, -1, /* unused */
585 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
586 34, -1 /* intrusion0, intrusion1 */
587};
588
Guenter Roeck6c009502012-07-01 08:23:15 -0700589static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
590 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
591
592static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
593 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
594
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800595static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
596{
597 if (mode == 0 && pwm == 255)
598 return off;
599 return mode + 1;
600}
601
602static int pwm_enable_to_reg(enum pwm_enable mode)
603{
604 if (mode == off)
605 return 0;
606 return mode - 1;
607}
608
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700609/*
610 * Conversions
611 */
612
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800613/* 1 is DC mode, output in ms */
614static unsigned int step_time_from_reg(u8 reg, u8 mode)
615{
616 return mode ? 400 * reg : 100 * reg;
617}
618
619static u8 step_time_to_reg(unsigned int msec, u8 mode)
620{
621 return clamp_val((mode ? (msec + 200) / 400 :
622 (msec + 50) / 100), 1, 255);
623}
624
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800625static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
626{
627 if (reg == 0 || reg == 255)
628 return 0;
629 return 1350000U / (reg << divreg);
630}
631
632static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
633{
634 if ((reg & 0xff1f) == 0xff1f)
635 return 0;
636
637 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
638
639 if (reg == 0)
640 return 0;
641
642 return 1350000U / reg;
643}
644
645static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
646{
647 if (reg == 0 || reg == 0xffff)
648 return 0;
649
650 /*
651 * Even though the registers are 16 bit wide, the fan divisor
652 * still applies.
653 */
654 return 1350000U / (reg << divreg);
655}
656
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800657static u16 fan_to_reg(u32 fan, unsigned int divreg)
658{
659 if (!fan)
660 return 0;
661
662 return (1350000U / fan) >> divreg;
663}
664
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800665static inline unsigned int
666div_from_reg(u8 reg)
667{
668 return 1 << reg;
669}
670
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700671/*
672 * Some of the voltage inputs have internal scaling, the tables below
673 * contain 8 (the ADC LSB in mV) * scaling factor * 100
674 */
675static const u16 scale_in[15] = {
676 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
677 800, 800
678};
679
680static inline long in_from_reg(u8 reg, u8 nr)
681{
682 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
683}
684
685static inline u8 in_to_reg(u32 val, u8 nr)
686{
687 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
688}
689
690/*
691 * Data structures and manipulation thereof
692 */
693
694struct nct6775_data {
695 int addr; /* IO base of hw monitor block */
696 enum kinds kind;
697 const char *name;
698
699 struct device *hwmon_dev;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700700 struct attribute_group *group_in;
701 struct attribute_group *group_fan;
702 struct attribute_group *group_temp;
703 struct attribute_group *group_pwm;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700704
Guenter Roeckb7a61352013-04-02 22:14:06 -0700705 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
706 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800707 */
708 u8 temp_src[NUM_TEMP];
709 u16 reg_temp_config[NUM_TEMP];
710 const char * const *temp_label;
711 int temp_label_num;
712
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700713 u16 REG_CONFIG;
714 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800715 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700716 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700717
718 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700719 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700720
721 const u16 *REG_VIN;
722 const u16 *REG_IN_MINMAX[2];
723
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800724 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800725 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800726 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800727 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800728 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700729 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800730 const u16 *REG_FAN_TIME[3];
731
732 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800733
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800734 const u8 *REG_PWM_MODE;
735 const u8 *PWM_MODE_MASK;
736
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800737 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
738 * [3]=pwm_max, [4]=pwm_step,
739 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800740 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800741 const u16 *REG_PWM_READ;
742
Guenter Roeck6c009502012-07-01 08:23:15 -0700743 const u16 *REG_CRITICAL_PWM_ENABLE;
744 u8 CRITICAL_PWM_ENABLE_MASK;
745 const u16 *REG_CRITICAL_PWM;
746
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800747 const u16 *REG_AUTO_TEMP;
748 const u16 *REG_AUTO_PWM;
749
750 const u16 *REG_CRITICAL_TEMP;
751 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
752
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800753 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800754 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800755 const u16 *REG_WEIGHT_TEMP_SEL;
756 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
757
Guenter Roeckaa136e52012-12-04 03:26:05 -0800758 const u16 *REG_TEMP_OFFSET;
759
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700760 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700761 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700762
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800763 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
764 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
765
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700766 struct mutex update_lock;
767 bool valid; /* true if following fields are valid */
768 unsigned long last_updated; /* In jiffies */
769
770 /* Register values */
771 u8 bank; /* current register bank */
772 u8 in_num; /* number of in inputs we have */
773 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800774 unsigned int rpm[5];
775 u16 fan_min[5];
Guenter Roeck5c25d952012-12-11 07:29:06 -0800776 u8 fan_pulses[5];
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800777 u8 fan_div[5];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800778 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800779 u8 has_fan; /* some fan inputs can be disabled */
780 u8 has_fan_min; /* some fans don't have min register */
781 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700782
Guenter Roeck6c009502012-07-01 08:23:15 -0700783 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700784 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800785 u8 temp_fixed_num; /* 3 or 6 */
786 u8 temp_type[NUM_TEMP_FIXED];
787 s8 temp_offset[NUM_TEMP_FIXED];
788 s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
789 * 3=temp_crit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700790 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700791 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700792
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800793 u8 pwm_num; /* number of pwm */
794 u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
795 enum pwm_enable pwm_enable[5];
796 /* 0->off
797 * 1->manual
798 * 2->thermal cruise mode (also called SmartFan I)
799 * 3->fan speed cruise mode
800 * 4->SmartFan III
801 * 5->enhanced variable thermal cruise (SmartFan IV)
802 */
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800803 u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
804 * [3]=pwm_max, [4]=pwm_step,
805 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800806 */
807
808 u8 target_temp[5];
809 u8 target_temp_mask;
810 u32 target_speed[5];
811 u32 target_speed_tolerance[5];
812 u8 speed_tolerance_limit;
813
814 u8 temp_tolerance[2][5];
815 u8 tolerance_mask;
816
817 u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
818
819 /* Automatic fan speed control registers */
820 int auto_pwm_num;
821 u8 auto_pwm[5][7];
822 u8 auto_temp[5][7];
823 u8 pwm_temp_sel[5];
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800824 u8 pwm_weight_temp_sel[5];
825 u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol,
826 * 2->temp_base
827 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800828
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700829 u8 vid;
830 u8 vrm;
831
Guenter Roeckf73cf632013-03-18 09:22:50 -0700832 bool have_vid;
833
Guenter Roeckaa136e52012-12-04 03:26:05 -0800834 u16 have_temp;
835 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700836 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800837#ifdef CONFIG_PM
838 /* Remember extra register values over suspend/resume */
839 u8 vbat;
840 u8 fandiv1;
841 u8 fandiv2;
842#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700843};
844
845struct nct6775_sio_data {
846 int sioreg;
847 enum kinds kind;
848};
849
Guenter Roeckf73cf632013-03-18 09:22:50 -0700850struct sensor_device_template {
851 struct device_attribute dev_attr;
852 union {
853 struct {
854 u8 nr;
855 u8 index;
856 } s;
857 int index;
858 } u;
859 bool s2; /* true if both index and nr are used */
860};
861
862struct sensor_device_attr_u {
863 union {
864 struct sensor_device_attribute a1;
865 struct sensor_device_attribute_2 a2;
866 } u;
867 char name[32];
868};
869
870#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
871 .attr = {.name = _template, .mode = _mode }, \
872 .show = _show, \
873 .store = _store, \
874}
875
876#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
877 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
878 .u.index = _index, \
879 .s2 = false }
880
881#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
882 _nr, _index) \
883 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
884 .u.s.index = _index, \
885 .u.s.nr = _nr, \
886 .s2 = true }
887
888#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
889static struct sensor_device_template sensor_dev_template_##_name \
890 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
891 _index)
892
893#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
894 _nr, _index) \
895static struct sensor_device_template sensor_dev_template_##_name \
896 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
897 _nr, _index)
898
899struct sensor_template_group {
900 struct sensor_device_template **templates;
901 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
902 int base;
903};
904
905static struct attribute_group *
906nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
907 int repeat)
908{
909 struct attribute_group *group;
910 struct sensor_device_attr_u *su;
911 struct sensor_device_attribute *a;
912 struct sensor_device_attribute_2 *a2;
913 struct attribute **attrs;
914 struct sensor_device_template **t;
915 int err, i, j, count;
916
917 if (repeat <= 0)
918 return ERR_PTR(-EINVAL);
919
920 t = tg->templates;
921 for (count = 0; *t; t++, count++)
922 ;
923
924 if (count == 0)
925 return ERR_PTR(-EINVAL);
926
927 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
928 if (group == NULL)
929 return ERR_PTR(-ENOMEM);
930
931 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
932 GFP_KERNEL);
933 if (attrs == NULL)
934 return ERR_PTR(-ENOMEM);
935
936 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
937 GFP_KERNEL);
938 if (su == NULL)
939 return ERR_PTR(-ENOMEM);
940
941 group->attrs = attrs;
942 group->is_visible = tg->is_visible;
943
944 for (i = 0; i < repeat; i++) {
945 t = tg->templates;
946 for (j = 0; *t != NULL; j++) {
947 snprintf(su->name, sizeof(su->name),
948 (*t)->dev_attr.attr.name, tg->base + i);
949 if ((*t)->s2) {
950 a2 = &su->u.a2;
951 a2->dev_attr.attr.name = su->name;
952 a2->nr = (*t)->u.s.nr + i;
953 a2->index = (*t)->u.s.index;
954 a2->dev_attr.attr.mode =
955 (*t)->dev_attr.attr.mode;
956 a2->dev_attr.show = (*t)->dev_attr.show;
957 a2->dev_attr.store = (*t)->dev_attr.store;
958 *attrs = &a2->dev_attr.attr;
959 } else {
960 a = &su->u.a1;
961 a->dev_attr.attr.name = su->name;
962 a->index = (*t)->u.index + i;
963 a->dev_attr.attr.mode =
964 (*t)->dev_attr.attr.mode;
965 a->dev_attr.show = (*t)->dev_attr.show;
966 a->dev_attr.store = (*t)->dev_attr.store;
967 *attrs = &a->dev_attr.attr;
968 }
969 attrs++;
970 su++;
971 t++;
972 }
973 }
974
975 err = sysfs_create_group(&dev->kobj, group);
976 if (err)
977 return ERR_PTR(-ENOMEM);
978
979 return group;
980}
981
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700982static bool is_word_sized(struct nct6775_data *data, u16 reg)
983{
984 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -0700985 case nct6106:
986 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
987 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
988 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700989 case nct6775:
990 return (((reg & 0xff00) == 0x100 ||
991 (reg & 0xff00) == 0x200) &&
992 ((reg & 0x00ff) == 0x50 ||
993 (reg & 0x00ff) == 0x53 ||
994 (reg & 0x00ff) == 0x55)) ||
995 (reg & 0xfff0) == 0x630 ||
996 reg == 0x640 || reg == 0x642 ||
997 reg == 0x662 ||
998 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
999 reg == 0x73 || reg == 0x75 || reg == 0x77;
1000 case nct6776:
1001 return (((reg & 0xff00) == 0x100 ||
1002 (reg & 0xff00) == 0x200) &&
1003 ((reg & 0x00ff) == 0x50 ||
1004 (reg & 0x00ff) == 0x53 ||
1005 (reg & 0x00ff) == 0x55)) ||
1006 (reg & 0xfff0) == 0x630 ||
1007 reg == 0x402 ||
1008 reg == 0x640 || reg == 0x642 ||
1009 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1010 reg == 0x73 || reg == 0x75 || reg == 0x77;
1011 case nct6779:
1012 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
1013 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
1014 reg == 0x402 ||
1015 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1016 reg == 0x640 || reg == 0x642 ||
1017 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
1018 reg == 0x7b;
1019 }
1020 return false;
1021}
1022
1023/*
1024 * On older chips, only registers 0x50-0x5f are banked.
1025 * On more recent chips, all registers are banked.
1026 * Assume that is the case and set the bank number for each access.
1027 * Cache the bank number so it only needs to be set if it changes.
1028 */
1029static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1030{
1031 u8 bank = reg >> 8;
1032 if (data->bank != bank) {
1033 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1034 outb_p(bank, data->addr + DATA_REG_OFFSET);
1035 data->bank = bank;
1036 }
1037}
1038
1039static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1040{
1041 int res, word_sized = is_word_sized(data, reg);
1042
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001043 nct6775_set_bank(data, reg);
1044 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1045 res = inb_p(data->addr + DATA_REG_OFFSET);
1046 if (word_sized) {
1047 outb_p((reg & 0xff) + 1,
1048 data->addr + ADDR_REG_OFFSET);
1049 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1050 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001051 return res;
1052}
1053
1054static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1055{
1056 int word_sized = is_word_sized(data, reg);
1057
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001058 nct6775_set_bank(data, reg);
1059 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1060 if (word_sized) {
1061 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1062 outb_p((reg & 0xff) + 1,
1063 data->addr + ADDR_REG_OFFSET);
1064 }
1065 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001066 return 0;
1067}
1068
Guenter Roeckaa136e52012-12-04 03:26:05 -08001069/* We left-align 8-bit temperature values to make the code simpler */
1070static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1071{
1072 u16 res;
1073
1074 res = nct6775_read_value(data, reg);
1075 if (!is_word_sized(data, reg))
1076 res <<= 8;
1077
1078 return res;
1079}
1080
1081static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1082{
1083 if (!is_word_sized(data, reg))
1084 value >>= 8;
1085 return nct6775_write_value(data, reg, value);
1086}
1087
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001088/* This function assumes that the caller holds data->update_lock */
1089static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1090{
1091 u8 reg;
1092
1093 switch (nr) {
1094 case 0:
1095 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1096 | (data->fan_div[0] & 0x7);
1097 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1098 break;
1099 case 1:
1100 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1101 | ((data->fan_div[1] << 4) & 0x70);
1102 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1103 break;
1104 case 2:
1105 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1106 | (data->fan_div[2] & 0x7);
1107 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1108 break;
1109 case 3:
1110 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1111 | ((data->fan_div[3] << 4) & 0x70);
1112 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1113 break;
1114 }
1115}
1116
1117static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1118{
1119 if (data->kind == nct6775)
1120 nct6775_write_fan_div(data, nr);
1121}
1122
1123static void nct6775_update_fan_div(struct nct6775_data *data)
1124{
1125 u8 i;
1126
1127 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1128 data->fan_div[0] = i & 0x7;
1129 data->fan_div[1] = (i & 0x70) >> 4;
1130 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1131 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001132 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001133 data->fan_div[3] = (i & 0x70) >> 4;
1134}
1135
1136static void nct6775_update_fan_div_common(struct nct6775_data *data)
1137{
1138 if (data->kind == nct6775)
1139 nct6775_update_fan_div(data);
1140}
1141
1142static void nct6775_init_fan_div(struct nct6775_data *data)
1143{
1144 int i;
1145
1146 nct6775_update_fan_div_common(data);
1147 /*
1148 * For all fans, start with highest divider value if the divider
1149 * register is not initialized. This ensures that we get a
1150 * reading from the fan count register, even if it is not optimal.
1151 * We'll compute a better divider later on.
1152 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001153 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001154 if (!(data->has_fan & (1 << i)))
1155 continue;
1156 if (data->fan_div[i] == 0) {
1157 data->fan_div[i] = 7;
1158 nct6775_write_fan_div_common(data, i);
1159 }
1160 }
1161}
1162
1163static void nct6775_init_fan_common(struct device *dev,
1164 struct nct6775_data *data)
1165{
1166 int i;
1167 u8 reg;
1168
1169 if (data->has_fan_div)
1170 nct6775_init_fan_div(data);
1171
1172 /*
1173 * If fan_min is not set (0), set it to 0xff to disable it. This
1174 * prevents the unnecessary warning when fanX_min is reported as 0.
1175 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001176 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001177 if (data->has_fan_min & (1 << i)) {
1178 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1179 if (!reg)
1180 nct6775_write_value(data, data->REG_FAN_MIN[i],
1181 data->has_fan_div ? 0xff
1182 : 0xff1f);
1183 }
1184 }
1185}
1186
1187static void nct6775_select_fan_div(struct device *dev,
1188 struct nct6775_data *data, int nr, u16 reg)
1189{
1190 u8 fan_div = data->fan_div[nr];
1191 u16 fan_min;
1192
1193 if (!data->has_fan_div)
1194 return;
1195
1196 /*
1197 * If we failed to measure the fan speed, or the reported value is not
1198 * in the optimal range, and the clock divider can be modified,
1199 * let's try that for next time.
1200 */
1201 if (reg == 0x00 && fan_div < 0x07)
1202 fan_div++;
1203 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1204 fan_div--;
1205
1206 if (fan_div != data->fan_div[nr]) {
1207 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1208 nr + 1, div_from_reg(data->fan_div[nr]),
1209 div_from_reg(fan_div));
1210
1211 /* Preserve min limit if possible */
1212 if (data->has_fan_min & (1 << nr)) {
1213 fan_min = data->fan_min[nr];
1214 if (fan_div > data->fan_div[nr]) {
1215 if (fan_min != 255 && fan_min > 1)
1216 fan_min >>= 1;
1217 } else {
1218 if (fan_min != 255) {
1219 fan_min <<= 1;
1220 if (fan_min > 254)
1221 fan_min = 254;
1222 }
1223 }
1224 if (fan_min != data->fan_min[nr]) {
1225 data->fan_min[nr] = fan_min;
1226 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1227 fan_min);
1228 }
1229 }
1230 data->fan_div[nr] = fan_div;
1231 nct6775_write_fan_div_common(data, nr);
1232 }
1233}
1234
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001235static void nct6775_update_pwm(struct device *dev)
1236{
1237 struct nct6775_data *data = dev_get_drvdata(dev);
1238 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001239 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001240 bool duty_is_dc;
1241
1242 for (i = 0; i < data->pwm_num; i++) {
1243 if (!(data->has_pwm & (1 << i)))
1244 continue;
1245
1246 duty_is_dc = data->REG_PWM_MODE[i] &&
1247 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1248 & data->PWM_MODE_MASK[i]);
1249 data->pwm_mode[i] = duty_is_dc;
1250
1251 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1252 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1253 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1254 data->pwm[j][i]
1255 = nct6775_read_value(data,
1256 data->REG_PWM[j][i]);
1257 }
1258 }
1259
1260 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1261 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001262
1263 if (!data->temp_tolerance[0][i] ||
1264 data->pwm_enable[i] != speed_cruise)
1265 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1266 if (!data->target_speed_tolerance[i] ||
1267 data->pwm_enable[i] == speed_cruise) {
1268 u8 t = fanmodecfg & 0x0f;
1269 if (data->REG_TOLERANCE_H) {
1270 t |= (nct6775_read_value(data,
1271 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1272 }
1273 data->target_speed_tolerance[i] = t;
1274 }
1275
1276 data->temp_tolerance[1][i] =
1277 nct6775_read_value(data,
1278 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1279
1280 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1281 data->pwm_temp_sel[i] = reg & 0x1f;
1282 /* If fan can stop, report floor as 0 */
1283 if (reg & 0x80)
1284 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001285
1286 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1287 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1288 /* If weight is disabled, report weight source as 0 */
1289 if (j == 1 && !(reg & 0x80))
1290 data->pwm_weight_temp_sel[i] = 0;
1291
1292 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001293 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001294 data->weight_temp[j][i]
1295 = nct6775_read_value(data,
1296 data->REG_WEIGHT_TEMP[j][i]);
1297 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001298 }
1299}
1300
1301static void nct6775_update_pwm_limits(struct device *dev)
1302{
1303 struct nct6775_data *data = dev_get_drvdata(dev);
1304 int i, j;
1305 u8 reg;
1306 u16 reg_t;
1307
1308 for (i = 0; i < data->pwm_num; i++) {
1309 if (!(data->has_pwm & (1 << i)))
1310 continue;
1311
Guenter Roeckc409fd42013-04-09 05:04:00 -07001312 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001313 data->fan_time[j][i] =
1314 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1315 }
1316
1317 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1318 /* Update only in matching mode or if never updated */
1319 if (!data->target_temp[i] ||
1320 data->pwm_enable[i] == thermal_cruise)
1321 data->target_temp[i] = reg_t & data->target_temp_mask;
1322 if (!data->target_speed[i] ||
1323 data->pwm_enable[i] == speed_cruise) {
1324 if (data->REG_TOLERANCE_H) {
1325 reg_t |= (nct6775_read_value(data,
1326 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1327 }
1328 data->target_speed[i] = reg_t;
1329 }
1330
1331 for (j = 0; j < data->auto_pwm_num; j++) {
1332 data->auto_pwm[i][j] =
1333 nct6775_read_value(data,
1334 NCT6775_AUTO_PWM(data, i, j));
1335 data->auto_temp[i][j] =
1336 nct6775_read_value(data,
1337 NCT6775_AUTO_TEMP(data, i, j));
1338 }
1339
1340 /* critical auto_pwm temperature data */
1341 data->auto_temp[i][data->auto_pwm_num] =
1342 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1343
1344 switch (data->kind) {
1345 case nct6775:
1346 reg = nct6775_read_value(data,
1347 NCT6775_REG_CRITICAL_ENAB[i]);
1348 data->auto_pwm[i][data->auto_pwm_num] =
1349 (reg & 0x02) ? 0xff : 0x00;
1350 break;
1351 case nct6776:
1352 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1353 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001354 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001355 case nct6779:
1356 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001357 data->REG_CRITICAL_PWM_ENABLE[i]);
1358 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1359 reg = nct6775_read_value(data,
1360 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001361 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001362 reg = 0xff;
1363 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001364 break;
1365 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001366 }
1367}
1368
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001369static struct nct6775_data *nct6775_update_device(struct device *dev)
1370{
1371 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001372 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001373
1374 mutex_lock(&data->update_lock);
1375
Guenter Roeck6445e662013-04-21 09:13:28 -07001376 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001377 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001378 /* Fan clock dividers */
1379 nct6775_update_fan_div_common(data);
1380
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001381 /* Measured voltages and limits */
1382 for (i = 0; i < data->in_num; i++) {
1383 if (!(data->have_in & (1 << i)))
1384 continue;
1385
1386 data->in[i][0] = nct6775_read_value(data,
1387 data->REG_VIN[i]);
1388 data->in[i][1] = nct6775_read_value(data,
1389 data->REG_IN_MINMAX[0][i]);
1390 data->in[i][2] = nct6775_read_value(data,
1391 data->REG_IN_MINMAX[1][i]);
1392 }
1393
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001394 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001395 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001396 u16 reg;
1397
1398 if (!(data->has_fan & (1 << i)))
1399 continue;
1400
1401 reg = nct6775_read_value(data, data->REG_FAN[i]);
1402 data->rpm[i] = data->fan_from_reg(reg,
1403 data->fan_div[i]);
1404
1405 if (data->has_fan_min & (1 << i))
1406 data->fan_min[i] = nct6775_read_value(data,
1407 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001408 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001409 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1410 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001411
1412 nct6775_select_fan_div(dev, data, i, reg);
1413 }
1414
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001415 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001416 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001417
Guenter Roeckaa136e52012-12-04 03:26:05 -08001418 /* Measured temperatures and limits */
1419 for (i = 0; i < NUM_TEMP; i++) {
1420 if (!(data->have_temp & (1 << i)))
1421 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001422 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001423 if (data->reg_temp[j][i])
1424 data->temp[j][i]
1425 = nct6775_read_temp(data,
1426 data->reg_temp[j][i]);
1427 }
1428 if (!(data->have_temp_fixed & (1 << i)))
1429 continue;
1430 data->temp_offset[i]
1431 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1432 }
1433
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001434 data->alarms = 0;
1435 for (i = 0; i < NUM_REG_ALARM; i++) {
1436 u8 alarm;
1437 if (!data->REG_ALARM[i])
1438 continue;
1439 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1440 data->alarms |= ((u64)alarm) << (i << 3);
1441 }
1442
Guenter Roeck30846992013-06-24 22:21:59 -07001443 data->beeps = 0;
1444 for (i = 0; i < NUM_REG_BEEP; i++) {
1445 u8 beep;
1446 if (!data->REG_BEEP[i])
1447 continue;
1448 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1449 data->beeps |= ((u64)beep) << (i << 3);
1450 }
1451
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001452 data->last_updated = jiffies;
1453 data->valid = true;
1454 }
1455
1456 mutex_unlock(&data->update_lock);
1457 return data;
1458}
1459
1460/*
1461 * Sysfs callback functions
1462 */
1463static ssize_t
1464show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1465{
1466 struct nct6775_data *data = nct6775_update_device(dev);
1467 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1468 int nr = sattr->nr;
1469 int index = sattr->index;
1470 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1471}
1472
1473static ssize_t
1474store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1475 size_t count)
1476{
1477 struct nct6775_data *data = dev_get_drvdata(dev);
1478 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1479 int nr = sattr->nr;
1480 int index = sattr->index;
1481 unsigned long val;
1482 int err = kstrtoul(buf, 10, &val);
1483 if (err < 0)
1484 return err;
1485 mutex_lock(&data->update_lock);
1486 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001487 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001488 data->in[nr][index]);
1489 mutex_unlock(&data->update_lock);
1490 return count;
1491}
1492
1493static ssize_t
1494show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1495{
1496 struct nct6775_data *data = nct6775_update_device(dev);
1497 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1498 int nr = data->ALARM_BITS[sattr->index];
1499 return sprintf(buf, "%u\n",
1500 (unsigned int)((data->alarms >> nr) & 0x01));
1501}
1502
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001503static int find_temp_source(struct nct6775_data *data, int index, int count)
1504{
1505 int source = data->temp_src[index];
1506 int nr;
1507
1508 for (nr = 0; nr < count; nr++) {
1509 int src;
1510
1511 src = nct6775_read_value(data,
1512 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1513 if (src == source)
1514 return nr;
1515 }
1516 return -1;
1517}
1518
1519static ssize_t
1520show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1521{
1522 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1523 struct nct6775_data *data = nct6775_update_device(dev);
1524 unsigned int alarm = 0;
1525 int nr;
1526
1527 /*
1528 * For temperatures, there is no fixed mapping from registers to alarm
1529 * bits. Alarm bits are determined by the temperature source mapping.
1530 */
1531 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1532 if (nr >= 0) {
1533 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1534 alarm = (data->alarms >> bit) & 0x01;
1535 }
1536 return sprintf(buf, "%u\n", alarm);
1537}
1538
Guenter Roeck30846992013-06-24 22:21:59 -07001539static ssize_t
1540show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1541{
1542 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1543 struct nct6775_data *data = nct6775_update_device(dev);
1544 int nr = data->BEEP_BITS[sattr->index];
1545
1546 return sprintf(buf, "%u\n",
1547 (unsigned int)((data->beeps >> nr) & 0x01));
1548}
1549
1550static ssize_t
1551store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1552 size_t count)
1553{
1554 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1555 struct nct6775_data *data = dev_get_drvdata(dev);
1556 int nr = data->BEEP_BITS[sattr->index];
1557 int regindex = nr >> 3;
1558 unsigned long val;
1559
1560 int err = kstrtoul(buf, 10, &val);
1561 if (err < 0)
1562 return err;
1563 if (val > 1)
1564 return -EINVAL;
1565
1566 mutex_lock(&data->update_lock);
1567 if (val)
1568 data->beeps |= (1ULL << nr);
1569 else
1570 data->beeps &= ~(1ULL << nr);
1571 nct6775_write_value(data, data->REG_BEEP[regindex],
1572 (data->beeps >> (regindex << 3)) & 0xff);
1573 mutex_unlock(&data->update_lock);
1574 return count;
1575}
1576
1577static ssize_t
1578show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1579{
1580 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1581 struct nct6775_data *data = nct6775_update_device(dev);
1582 unsigned int beep = 0;
1583 int nr;
1584
1585 /*
1586 * For temperatures, there is no fixed mapping from registers to beep
1587 * enable bits. Beep enable bits are determined by the temperature
1588 * source mapping.
1589 */
1590 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1591 if (nr >= 0) {
1592 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1593 beep = (data->beeps >> bit) & 0x01;
1594 }
1595 return sprintf(buf, "%u\n", beep);
1596}
1597
1598static ssize_t
1599store_temp_beep(struct device *dev, struct device_attribute *attr,
1600 const char *buf, size_t count)
1601{
1602 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1603 struct nct6775_data *data = dev_get_drvdata(dev);
1604 int nr, bit, regindex;
1605 unsigned long val;
1606
1607 int err = kstrtoul(buf, 10, &val);
1608 if (err < 0)
1609 return err;
1610 if (val > 1)
1611 return -EINVAL;
1612
1613 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1614 if (nr < 0)
1615 return -ENODEV;
1616
1617 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1618 regindex = bit >> 3;
1619
1620 mutex_lock(&data->update_lock);
1621 if (val)
1622 data->beeps |= (1ULL << bit);
1623 else
1624 data->beeps &= ~(1ULL << bit);
1625 nct6775_write_value(data, data->REG_BEEP[regindex],
1626 (data->beeps >> (regindex << 3)) & 0xff);
1627 mutex_unlock(&data->update_lock);
1628
1629 return count;
1630}
1631
Guenter Roeckf73cf632013-03-18 09:22:50 -07001632static umode_t nct6775_in_is_visible(struct kobject *kobj,
1633 struct attribute *attr, int index)
1634{
1635 struct device *dev = container_of(kobj, struct device, kobj);
1636 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001637 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001638
Guenter Roeckf73cf632013-03-18 09:22:50 -07001639 if (!(data->have_in & (1 << in)))
1640 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001641
Guenter Roeckf73cf632013-03-18 09:22:50 -07001642 return attr->mode;
1643}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001644
Guenter Roeckf73cf632013-03-18 09:22:50 -07001645SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1646SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001647SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1648 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001649SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1650 store_in_reg, 0, 1);
1651SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1652 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001653
Guenter Roeckf73cf632013-03-18 09:22:50 -07001654/*
1655 * nct6775_in_is_visible uses the index into the following array
1656 * to determine if attributes should be created or not.
1657 * Any change in order or content must be matched.
1658 */
1659static struct sensor_device_template *nct6775_attributes_in_template[] = {
1660 &sensor_dev_template_in_input,
1661 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001662 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001663 &sensor_dev_template_in_min,
1664 &sensor_dev_template_in_max,
1665 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001666};
1667
Guenter Roeckf73cf632013-03-18 09:22:50 -07001668static struct sensor_template_group nct6775_in_template_group = {
1669 .templates = nct6775_attributes_in_template,
1670 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001671};
1672
1673static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001674show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1675{
1676 struct nct6775_data *data = nct6775_update_device(dev);
1677 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1678 int nr = sattr->index;
1679 return sprintf(buf, "%d\n", data->rpm[nr]);
1680}
1681
1682static ssize_t
1683show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1684{
1685 struct nct6775_data *data = nct6775_update_device(dev);
1686 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1687 int nr = sattr->index;
1688 return sprintf(buf, "%d\n",
1689 data->fan_from_reg_min(data->fan_min[nr],
1690 data->fan_div[nr]));
1691}
1692
1693static ssize_t
1694show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1695{
1696 struct nct6775_data *data = nct6775_update_device(dev);
1697 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1698 int nr = sattr->index;
1699 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1700}
1701
1702static ssize_t
1703store_fan_min(struct device *dev, struct device_attribute *attr,
1704 const char *buf, size_t count)
1705{
1706 struct nct6775_data *data = dev_get_drvdata(dev);
1707 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1708 int nr = sattr->index;
1709 unsigned long val;
1710 int err;
1711 unsigned int reg;
1712 u8 new_div;
1713
1714 err = kstrtoul(buf, 10, &val);
1715 if (err < 0)
1716 return err;
1717
1718 mutex_lock(&data->update_lock);
1719 if (!data->has_fan_div) {
1720 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1721 if (!val) {
1722 val = 0xff1f;
1723 } else {
1724 if (val > 1350000U)
1725 val = 135000U;
1726 val = 1350000U / val;
1727 val = (val & 0x1f) | ((val << 3) & 0xff00);
1728 }
1729 data->fan_min[nr] = val;
1730 goto write_min; /* Leave fan divider alone */
1731 }
1732 if (!val) {
1733 /* No min limit, alarm disabled */
1734 data->fan_min[nr] = 255;
1735 new_div = data->fan_div[nr]; /* No change */
1736 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1737 goto write_div;
1738 }
1739 reg = 1350000U / val;
1740 if (reg >= 128 * 255) {
1741 /*
1742 * Speed below this value cannot possibly be represented,
1743 * even with the highest divider (128)
1744 */
1745 data->fan_min[nr] = 254;
1746 new_div = 7; /* 128 == (1 << 7) */
1747 dev_warn(dev,
1748 "fan%u low limit %lu below minimum %u, set to minimum\n",
1749 nr + 1, val, data->fan_from_reg_min(254, 7));
1750 } else if (!reg) {
1751 /*
1752 * Speed above this value cannot possibly be represented,
1753 * even with the lowest divider (1)
1754 */
1755 data->fan_min[nr] = 1;
1756 new_div = 0; /* 1 == (1 << 0) */
1757 dev_warn(dev,
1758 "fan%u low limit %lu above maximum %u, set to maximum\n",
1759 nr + 1, val, data->fan_from_reg_min(1, 0));
1760 } else {
1761 /*
1762 * Automatically pick the best divider, i.e. the one such
1763 * that the min limit will correspond to a register value
1764 * in the 96..192 range
1765 */
1766 new_div = 0;
1767 while (reg > 192 && new_div < 7) {
1768 reg >>= 1;
1769 new_div++;
1770 }
1771 data->fan_min[nr] = reg;
1772 }
1773
1774write_div:
1775 /*
1776 * Write both the fan clock divider (if it changed) and the new
1777 * fan min (unconditionally)
1778 */
1779 if (new_div != data->fan_div[nr]) {
1780 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1781 nr + 1, div_from_reg(data->fan_div[nr]),
1782 div_from_reg(new_div));
1783 data->fan_div[nr] = new_div;
1784 nct6775_write_fan_div_common(data, nr);
1785 /* Give the chip time to sample a new speed value */
1786 data->last_updated = jiffies;
1787 }
1788
1789write_min:
1790 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1791 mutex_unlock(&data->update_lock);
1792
1793 return count;
1794}
1795
Guenter Roeck5c25d952012-12-11 07:29:06 -08001796static ssize_t
1797show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1798{
1799 struct nct6775_data *data = nct6775_update_device(dev);
1800 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1801 int p = data->fan_pulses[sattr->index];
1802
1803 return sprintf(buf, "%d\n", p ? : 4);
1804}
1805
1806static ssize_t
1807store_fan_pulses(struct device *dev, struct device_attribute *attr,
1808 const char *buf, size_t count)
1809{
1810 struct nct6775_data *data = dev_get_drvdata(dev);
1811 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1812 int nr = sattr->index;
1813 unsigned long val;
1814 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001815 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001816
1817 err = kstrtoul(buf, 10, &val);
1818 if (err < 0)
1819 return err;
1820
1821 if (val > 4)
1822 return -EINVAL;
1823
1824 mutex_lock(&data->update_lock);
1825 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001826 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1827 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1828 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1829 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001830 mutex_unlock(&data->update_lock);
1831
1832 return count;
1833}
1834
Guenter Roeckf73cf632013-03-18 09:22:50 -07001835static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1836 struct attribute *attr, int index)
1837{
1838 struct device *dev = container_of(kobj, struct device, kobj);
1839 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001840 int fan = index / 6; /* fan index */
1841 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001842
1843 if (!(data->has_fan & (1 << fan)))
1844 return 0;
1845
1846 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1847 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001848 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001849 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001850 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1851 return 0;
1852 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001853 return 0;
1854
1855 return attr->mode;
1856}
1857
1858SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1859SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1860 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001861SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1862 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001863SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1864 store_fan_pulses, 0);
1865SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1866 store_fan_min, 0);
1867SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1868
1869/*
1870 * nct6775_fan_is_visible uses the index into the following array
1871 * to determine if attributes should be created or not.
1872 * Any change in order or content must be matched.
1873 */
1874static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1875 &sensor_dev_template_fan_input,
1876 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001877 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001878 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001879 &sensor_dev_template_fan_min, /* 4 */
1880 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001881 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001882};
1883
Guenter Roeckf73cf632013-03-18 09:22:50 -07001884static struct sensor_template_group nct6775_fan_template_group = {
1885 .templates = nct6775_attributes_fan_template,
1886 .is_visible = nct6775_fan_is_visible,
1887 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001888};
1889
1890static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001891show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1892{
1893 struct nct6775_data *data = nct6775_update_device(dev);
1894 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1895 int nr = sattr->index;
1896 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1897}
1898
1899static ssize_t
1900show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1901{
1902 struct nct6775_data *data = nct6775_update_device(dev);
1903 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1904 int nr = sattr->nr;
1905 int index = sattr->index;
1906
1907 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1908}
1909
1910static ssize_t
1911store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1912 size_t count)
1913{
1914 struct nct6775_data *data = dev_get_drvdata(dev);
1915 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1916 int nr = sattr->nr;
1917 int index = sattr->index;
1918 int err;
1919 long val;
1920
1921 err = kstrtol(buf, 10, &val);
1922 if (err < 0)
1923 return err;
1924
1925 mutex_lock(&data->update_lock);
1926 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1927 nct6775_write_temp(data, data->reg_temp[index][nr],
1928 data->temp[index][nr]);
1929 mutex_unlock(&data->update_lock);
1930 return count;
1931}
1932
1933static ssize_t
1934show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1935{
1936 struct nct6775_data *data = nct6775_update_device(dev);
1937 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1938
1939 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1940}
1941
1942static ssize_t
1943store_temp_offset(struct device *dev, struct device_attribute *attr,
1944 const char *buf, size_t count)
1945{
1946 struct nct6775_data *data = dev_get_drvdata(dev);
1947 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1948 int nr = sattr->index;
1949 long val;
1950 int err;
1951
1952 err = kstrtol(buf, 10, &val);
1953 if (err < 0)
1954 return err;
1955
1956 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1957
1958 mutex_lock(&data->update_lock);
1959 data->temp_offset[nr] = val;
1960 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1961 mutex_unlock(&data->update_lock);
1962
1963 return count;
1964}
1965
1966static ssize_t
1967show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1968{
1969 struct nct6775_data *data = nct6775_update_device(dev);
1970 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1971 int nr = sattr->index;
1972 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
1973}
1974
1975static ssize_t
1976store_temp_type(struct device *dev, struct device_attribute *attr,
1977 const char *buf, size_t count)
1978{
1979 struct nct6775_data *data = nct6775_update_device(dev);
1980 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1981 int nr = sattr->index;
1982 unsigned long val;
1983 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001984 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001985
1986 err = kstrtoul(buf, 10, &val);
1987 if (err < 0)
1988 return err;
1989
1990 if (val != 1 && val != 3 && val != 4)
1991 return -EINVAL;
1992
1993 mutex_lock(&data->update_lock);
1994
1995 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07001996 vbit = 0x02 << nr;
1997 dbit = data->DIODE_MASK << nr;
1998 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
1999 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002000 switch (val) {
2001 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002002 vbat |= vbit;
2003 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002004 break;
2005 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002006 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002007 break;
2008 case 4: /* thermistor */
2009 break;
2010 }
2011 nct6775_write_value(data, data->REG_VBAT, vbat);
2012 nct6775_write_value(data, data->REG_DIODE, diode);
2013
2014 mutex_unlock(&data->update_lock);
2015 return count;
2016}
2017
Guenter Roeckf73cf632013-03-18 09:22:50 -07002018static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2019 struct attribute *attr, int index)
2020{
2021 struct device *dev = container_of(kobj, struct device, kobj);
2022 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002023 int temp = index / 10; /* temp index */
2024 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002025
2026 if (!(data->have_temp & (1 << temp)))
2027 return 0;
2028
2029 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2030 return 0; /* alarm */
2031
Guenter Roeck30846992013-06-24 22:21:59 -07002032 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2033 return 0; /* beep */
2034
2035 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002036 return 0;
2037
Guenter Roeck30846992013-06-24 22:21:59 -07002038 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002039 return 0;
2040
Guenter Roeck30846992013-06-24 22:21:59 -07002041 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002042 return 0;
2043
Guenter Roeck30846992013-06-24 22:21:59 -07002044 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002045 return 0;
2046
2047 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002048 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002049 return 0;
2050
2051 return attr->mode;
2052}
2053
2054SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2055SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2056SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2057 store_temp, 0, 1);
2058SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2059 show_temp, store_temp, 0, 2);
2060SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2061 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002062SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2063 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002064SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2065 show_temp_offset, store_temp_offset, 0);
2066SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2067 store_temp_type, 0);
2068SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002069SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2070 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002071
2072/*
2073 * nct6775_temp_is_visible uses the index into the following array
2074 * to determine if attributes should be created or not.
2075 * Any change in order or content must be matched.
2076 */
2077static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2078 &sensor_dev_template_temp_input,
2079 &sensor_dev_template_temp_label,
2080 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002081 &sensor_dev_template_temp_beep, /* 3 */
2082 &sensor_dev_template_temp_max, /* 4 */
2083 &sensor_dev_template_temp_max_hyst, /* 5 */
2084 &sensor_dev_template_temp_crit, /* 6 */
2085 &sensor_dev_template_temp_lcrit, /* 7 */
2086 &sensor_dev_template_temp_offset, /* 8 */
2087 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002088 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002089};
2090
Guenter Roeckf73cf632013-03-18 09:22:50 -07002091static struct sensor_template_group nct6775_temp_template_group = {
2092 .templates = nct6775_attributes_temp_template,
2093 .is_visible = nct6775_temp_is_visible,
2094 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002095};
2096
Guenter Roeckaa136e52012-12-04 03:26:05 -08002097static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002098show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2099{
2100 struct nct6775_data *data = nct6775_update_device(dev);
2101 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2102
2103 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2104}
2105
2106static ssize_t
2107store_pwm_mode(struct device *dev, struct device_attribute *attr,
2108 const char *buf, size_t count)
2109{
2110 struct nct6775_data *data = dev_get_drvdata(dev);
2111 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2112 int nr = sattr->index;
2113 unsigned long val;
2114 int err;
2115 u8 reg;
2116
2117 err = kstrtoul(buf, 10, &val);
2118 if (err < 0)
2119 return err;
2120
2121 if (val > 1)
2122 return -EINVAL;
2123
2124 /* Setting DC mode is not supported for all chips/channels */
2125 if (data->REG_PWM_MODE[nr] == 0) {
2126 if (val)
2127 return -EINVAL;
2128 return count;
2129 }
2130
2131 mutex_lock(&data->update_lock);
2132 data->pwm_mode[nr] = val;
2133 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2134 reg &= ~data->PWM_MODE_MASK[nr];
2135 if (val)
2136 reg |= data->PWM_MODE_MASK[nr];
2137 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2138 mutex_unlock(&data->update_lock);
2139 return count;
2140}
2141
2142static ssize_t
2143show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2144{
2145 struct nct6775_data *data = nct6775_update_device(dev);
2146 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2147 int nr = sattr->nr;
2148 int index = sattr->index;
2149 int pwm;
2150
2151 /*
2152 * For automatic fan control modes, show current pwm readings.
2153 * Otherwise, show the configured value.
2154 */
2155 if (index == 0 && data->pwm_enable[nr] > manual)
2156 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2157 else
2158 pwm = data->pwm[index][nr];
2159
2160 return sprintf(buf, "%d\n", pwm);
2161}
2162
2163static ssize_t
2164store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2165 size_t count)
2166{
2167 struct nct6775_data *data = dev_get_drvdata(dev);
2168 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2169 int nr = sattr->nr;
2170 int index = sattr->index;
2171 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002172 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2173 int maxval[7]
2174 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002175 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002176 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002177
2178 err = kstrtoul(buf, 10, &val);
2179 if (err < 0)
2180 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002181 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002182
2183 mutex_lock(&data->update_lock);
2184 data->pwm[index][nr] = val;
2185 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002186 if (index == 2) { /* floor: disable if val == 0 */
2187 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2188 reg &= 0x7f;
2189 if (val)
2190 reg |= 0x80;
2191 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2192 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002193 mutex_unlock(&data->update_lock);
2194 return count;
2195}
2196
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002197/* Returns 0 if OK, -EINVAL otherwise */
2198static int check_trip_points(struct nct6775_data *data, int nr)
2199{
2200 int i;
2201
2202 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2203 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2204 return -EINVAL;
2205 }
2206 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2207 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2208 return -EINVAL;
2209 }
2210 /* validate critical temperature and pwm if enabled (pwm > 0) */
2211 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2212 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2213 data->auto_temp[nr][data->auto_pwm_num] ||
2214 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2215 data->auto_pwm[nr][data->auto_pwm_num])
2216 return -EINVAL;
2217 }
2218 return 0;
2219}
2220
2221static void pwm_update_registers(struct nct6775_data *data, int nr)
2222{
2223 u8 reg;
2224
2225 switch (data->pwm_enable[nr]) {
2226 case off:
2227 case manual:
2228 break;
2229 case speed_cruise:
2230 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2231 reg = (reg & ~data->tolerance_mask) |
2232 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2233 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2234 nct6775_write_value(data, data->REG_TARGET[nr],
2235 data->target_speed[nr] & 0xff);
2236 if (data->REG_TOLERANCE_H) {
2237 reg = (data->target_speed[nr] >> 8) & 0x0f;
2238 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2239 nct6775_write_value(data,
2240 data->REG_TOLERANCE_H[nr],
2241 reg);
2242 }
2243 break;
2244 case thermal_cruise:
2245 nct6775_write_value(data, data->REG_TARGET[nr],
2246 data->target_temp[nr]);
2247 /* intentional */
2248 default:
2249 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2250 reg = (reg & ~data->tolerance_mask) |
2251 data->temp_tolerance[0][nr];
2252 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2253 break;
2254 }
2255}
2256
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002257static ssize_t
2258show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2259{
2260 struct nct6775_data *data = nct6775_update_device(dev);
2261 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2262
2263 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2264}
2265
2266static ssize_t
2267store_pwm_enable(struct device *dev, struct device_attribute *attr,
2268 const char *buf, size_t count)
2269{
2270 struct nct6775_data *data = dev_get_drvdata(dev);
2271 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2272 int nr = sattr->index;
2273 unsigned long val;
2274 int err;
2275 u16 reg;
2276
2277 err = kstrtoul(buf, 10, &val);
2278 if (err < 0)
2279 return err;
2280
2281 if (val > sf4)
2282 return -EINVAL;
2283
2284 if (val == sf3 && data->kind != nct6775)
2285 return -EINVAL;
2286
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002287 if (val == sf4 && check_trip_points(data, nr)) {
2288 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2289 dev_err(dev, "Adjust trip points and try again\n");
2290 return -EINVAL;
2291 }
2292
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002293 mutex_lock(&data->update_lock);
2294 data->pwm_enable[nr] = val;
2295 if (val == off) {
2296 /*
2297 * turn off pwm control: select manual mode, set pwm to maximum
2298 */
2299 data->pwm[0][nr] = 255;
2300 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2301 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002302 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002303 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2304 reg &= 0x0f;
2305 reg |= pwm_enable_to_reg(val) << 4;
2306 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2307 mutex_unlock(&data->update_lock);
2308 return count;
2309}
2310
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002311static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002312show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002313{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002314 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002315
2316 for (i = 0; i < NUM_TEMP; i++) {
2317 if (!(data->have_temp & (1 << i)))
2318 continue;
2319 if (src == data->temp_src[i]) {
2320 sel = i + 1;
2321 break;
2322 }
2323 }
2324
2325 return sprintf(buf, "%d\n", sel);
2326}
2327
2328static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002329show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2330{
2331 struct nct6775_data *data = nct6775_update_device(dev);
2332 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2333 int index = sattr->index;
2334
2335 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2336}
2337
2338static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002339store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2340 const char *buf, size_t count)
2341{
2342 struct nct6775_data *data = nct6775_update_device(dev);
2343 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2344 int nr = sattr->index;
2345 unsigned long val;
2346 int err, reg, src;
2347
2348 err = kstrtoul(buf, 10, &val);
2349 if (err < 0)
2350 return err;
2351 if (val == 0 || val > NUM_TEMP)
2352 return -EINVAL;
2353 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2354 return -EINVAL;
2355
2356 mutex_lock(&data->update_lock);
2357 src = data->temp_src[val - 1];
2358 data->pwm_temp_sel[nr] = src;
2359 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2360 reg &= 0xe0;
2361 reg |= src;
2362 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2363 mutex_unlock(&data->update_lock);
2364
2365 return count;
2366}
2367
2368static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002369show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2370 char *buf)
2371{
2372 struct nct6775_data *data = nct6775_update_device(dev);
2373 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2374 int index = sattr->index;
2375
2376 return show_pwm_temp_sel_common(data, buf,
2377 data->pwm_weight_temp_sel[index]);
2378}
2379
2380static ssize_t
2381store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2382 const char *buf, size_t count)
2383{
2384 struct nct6775_data *data = nct6775_update_device(dev);
2385 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2386 int nr = sattr->index;
2387 unsigned long val;
2388 int err, reg, src;
2389
2390 err = kstrtoul(buf, 10, &val);
2391 if (err < 0)
2392 return err;
2393 if (val > NUM_TEMP)
2394 return -EINVAL;
2395 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2396 !data->temp_src[val - 1]))
2397 return -EINVAL;
2398
2399 mutex_lock(&data->update_lock);
2400 if (val) {
2401 src = data->temp_src[val - 1];
2402 data->pwm_weight_temp_sel[nr] = src;
2403 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2404 reg &= 0xe0;
2405 reg |= (src | 0x80);
2406 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2407 } else {
2408 data->pwm_weight_temp_sel[nr] = 0;
2409 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2410 reg &= 0x7f;
2411 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2412 }
2413 mutex_unlock(&data->update_lock);
2414
2415 return count;
2416}
2417
2418static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002419show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2420{
2421 struct nct6775_data *data = nct6775_update_device(dev);
2422 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2423
2424 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2425}
2426
2427static ssize_t
2428store_target_temp(struct device *dev, struct device_attribute *attr,
2429 const char *buf, size_t count)
2430{
2431 struct nct6775_data *data = dev_get_drvdata(dev);
2432 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2433 int nr = sattr->index;
2434 unsigned long val;
2435 int err;
2436
2437 err = kstrtoul(buf, 10, &val);
2438 if (err < 0)
2439 return err;
2440
2441 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2442 data->target_temp_mask);
2443
2444 mutex_lock(&data->update_lock);
2445 data->target_temp[nr] = val;
2446 pwm_update_registers(data, nr);
2447 mutex_unlock(&data->update_lock);
2448 return count;
2449}
2450
2451static ssize_t
2452show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2453{
2454 struct nct6775_data *data = nct6775_update_device(dev);
2455 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2456 int nr = sattr->index;
2457
2458 return sprintf(buf, "%d\n",
2459 fan_from_reg16(data->target_speed[nr],
2460 data->fan_div[nr]));
2461}
2462
2463static ssize_t
2464store_target_speed(struct device *dev, struct device_attribute *attr,
2465 const char *buf, size_t count)
2466{
2467 struct nct6775_data *data = dev_get_drvdata(dev);
2468 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2469 int nr = sattr->index;
2470 unsigned long val;
2471 int err;
2472 u16 speed;
2473
2474 err = kstrtoul(buf, 10, &val);
2475 if (err < 0)
2476 return err;
2477
2478 val = clamp_val(val, 0, 1350000U);
2479 speed = fan_to_reg(val, data->fan_div[nr]);
2480
2481 mutex_lock(&data->update_lock);
2482 data->target_speed[nr] = speed;
2483 pwm_update_registers(data, nr);
2484 mutex_unlock(&data->update_lock);
2485 return count;
2486}
2487
2488static ssize_t
2489show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2490 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", data->temp_tolerance[index][nr] * 1000);
2498}
2499
2500static ssize_t
2501store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2502 const char *buf, size_t count)
2503{
2504 struct nct6775_data *data = dev_get_drvdata(dev);
2505 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2506 int nr = sattr->nr;
2507 int index = sattr->index;
2508 unsigned long val;
2509 int err;
2510
2511 err = kstrtoul(buf, 10, &val);
2512 if (err < 0)
2513 return err;
2514
2515 /* Limit tolerance as needed */
2516 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2517
2518 mutex_lock(&data->update_lock);
2519 data->temp_tolerance[index][nr] = val;
2520 if (index)
2521 pwm_update_registers(data, nr);
2522 else
2523 nct6775_write_value(data,
2524 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2525 val);
2526 mutex_unlock(&data->update_lock);
2527 return count;
2528}
2529
2530/*
2531 * Fan speed tolerance is a tricky beast, since the associated register is
2532 * a tick counter, but the value is reported and configured as rpm.
2533 * Compute resulting low and high rpm values and report the difference.
2534 */
2535static ssize_t
2536show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2537 char *buf)
2538{
2539 struct nct6775_data *data = nct6775_update_device(dev);
2540 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2541 int nr = sattr->index;
2542 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2543 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2544 int tolerance;
2545
2546 if (low <= 0)
2547 low = 1;
2548 if (high > 0xffff)
2549 high = 0xffff;
2550 if (high < low)
2551 high = low;
2552
2553 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2554 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2555
2556 return sprintf(buf, "%d\n", tolerance);
2557}
2558
2559static ssize_t
2560store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2561 const char *buf, size_t count)
2562{
2563 struct nct6775_data *data = dev_get_drvdata(dev);
2564 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2565 int nr = sattr->index;
2566 unsigned long val;
2567 int err;
2568 int low, high;
2569
2570 err = kstrtoul(buf, 10, &val);
2571 if (err < 0)
2572 return err;
2573
2574 high = fan_from_reg16(data->target_speed[nr],
2575 data->fan_div[nr]) + val;
2576 low = fan_from_reg16(data->target_speed[nr],
2577 data->fan_div[nr]) - val;
2578 if (low <= 0)
2579 low = 1;
2580 if (high < low)
2581 high = low;
2582
2583 val = (fan_to_reg(low, data->fan_div[nr]) -
2584 fan_to_reg(high, data->fan_div[nr])) / 2;
2585
2586 /* Limit tolerance as needed */
2587 val = clamp_val(val, 0, data->speed_tolerance_limit);
2588
2589 mutex_lock(&data->update_lock);
2590 data->target_speed_tolerance[nr] = val;
2591 pwm_update_registers(data, nr);
2592 mutex_unlock(&data->update_lock);
2593 return count;
2594}
2595
Guenter Roeckf73cf632013-03-18 09:22:50 -07002596SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2597SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2598 store_pwm_mode, 0);
2599SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2600 store_pwm_enable, 0);
2601SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2602 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2603SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2604 show_target_temp, store_target_temp, 0);
2605SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2606 show_target_speed, store_target_speed, 0);
2607SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2608 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002609
2610/* Smart Fan registers */
2611
2612static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002613show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2614{
2615 struct nct6775_data *data = nct6775_update_device(dev);
2616 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2617 int nr = sattr->nr;
2618 int index = sattr->index;
2619
2620 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2621}
2622
2623static ssize_t
2624store_weight_temp(struct device *dev, struct device_attribute *attr,
2625 const char *buf, size_t count)
2626{
2627 struct nct6775_data *data = dev_get_drvdata(dev);
2628 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2629 int nr = sattr->nr;
2630 int index = sattr->index;
2631 unsigned long val;
2632 int err;
2633
2634 err = kstrtoul(buf, 10, &val);
2635 if (err < 0)
2636 return err;
2637
2638 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2639
2640 mutex_lock(&data->update_lock);
2641 data->weight_temp[index][nr] = val;
2642 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2643 mutex_unlock(&data->update_lock);
2644 return count;
2645}
2646
Guenter Roeckf73cf632013-03-18 09:22:50 -07002647SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2648 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2649SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2650 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2651SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2652 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2653SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2654 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2655SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2656 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2657SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2658 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002659
2660static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002661show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2662{
2663 struct nct6775_data *data = nct6775_update_device(dev);
2664 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2665 int nr = sattr->nr;
2666 int index = sattr->index;
2667
2668 return sprintf(buf, "%d\n",
2669 step_time_from_reg(data->fan_time[index][nr],
2670 data->pwm_mode[nr]));
2671}
2672
2673static ssize_t
2674store_fan_time(struct device *dev, struct device_attribute *attr,
2675 const char *buf, size_t count)
2676{
2677 struct nct6775_data *data = dev_get_drvdata(dev);
2678 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2679 int nr = sattr->nr;
2680 int index = sattr->index;
2681 unsigned long val;
2682 int err;
2683
2684 err = kstrtoul(buf, 10, &val);
2685 if (err < 0)
2686 return err;
2687
2688 val = step_time_to_reg(val, data->pwm_mode[nr]);
2689 mutex_lock(&data->update_lock);
2690 data->fan_time[index][nr] = val;
2691 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2692 mutex_unlock(&data->update_lock);
2693 return count;
2694}
2695
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002696static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002697show_name(struct device *dev, struct device_attribute *attr, char *buf)
2698{
2699 struct nct6775_data *data = dev_get_drvdata(dev);
2700
2701 return sprintf(buf, "%s\n", data->name);
2702}
2703
2704static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2705
2706static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002707show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2708{
2709 struct nct6775_data *data = nct6775_update_device(dev);
2710 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2711
2712 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2713}
2714
2715static ssize_t
2716store_auto_pwm(struct device *dev, struct device_attribute *attr,
2717 const char *buf, size_t count)
2718{
2719 struct nct6775_data *data = dev_get_drvdata(dev);
2720 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2721 int nr = sattr->nr;
2722 int point = sattr->index;
2723 unsigned long val;
2724 int err;
2725 u8 reg;
2726
2727 err = kstrtoul(buf, 10, &val);
2728 if (err < 0)
2729 return err;
2730 if (val > 255)
2731 return -EINVAL;
2732
2733 if (point == data->auto_pwm_num) {
2734 if (data->kind != nct6775 && !val)
2735 return -EINVAL;
2736 if (data->kind != nct6779 && val)
2737 val = 0xff;
2738 }
2739
2740 mutex_lock(&data->update_lock);
2741 data->auto_pwm[nr][point] = val;
2742 if (point < data->auto_pwm_num) {
2743 nct6775_write_value(data,
2744 NCT6775_AUTO_PWM(data, nr, point),
2745 data->auto_pwm[nr][point]);
2746 } else {
2747 switch (data->kind) {
2748 case nct6775:
2749 /* disable if needed (pwm == 0) */
2750 reg = nct6775_read_value(data,
2751 NCT6775_REG_CRITICAL_ENAB[nr]);
2752 if (val)
2753 reg |= 0x02;
2754 else
2755 reg &= ~0x02;
2756 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2757 reg);
2758 break;
2759 case nct6776:
2760 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002761 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002762 case nct6779:
Guenter Roeck6c009502012-07-01 08:23:15 -07002763 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002764 val);
2765 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002766 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002767 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002768 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002769 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002770 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002771 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002772 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002773 reg);
2774 break;
2775 }
2776 }
2777 mutex_unlock(&data->update_lock);
2778 return count;
2779}
2780
2781static ssize_t
2782show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2783{
2784 struct nct6775_data *data = nct6775_update_device(dev);
2785 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2786 int nr = sattr->nr;
2787 int point = sattr->index;
2788
2789 /*
2790 * We don't know for sure if the temperature is signed or unsigned.
2791 * Assume it is unsigned.
2792 */
2793 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2794}
2795
2796static ssize_t
2797store_auto_temp(struct device *dev, struct device_attribute *attr,
2798 const char *buf, size_t count)
2799{
2800 struct nct6775_data *data = dev_get_drvdata(dev);
2801 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2802 int nr = sattr->nr;
2803 int point = sattr->index;
2804 unsigned long val;
2805 int err;
2806
2807 err = kstrtoul(buf, 10, &val);
2808 if (err)
2809 return err;
2810 if (val > 255000)
2811 return -EINVAL;
2812
2813 mutex_lock(&data->update_lock);
2814 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2815 if (point < data->auto_pwm_num) {
2816 nct6775_write_value(data,
2817 NCT6775_AUTO_TEMP(data, nr, point),
2818 data->auto_temp[nr][point]);
2819 } else {
2820 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2821 data->auto_temp[nr][point]);
2822 }
2823 mutex_unlock(&data->update_lock);
2824 return count;
2825}
2826
Guenter Roeckf73cf632013-03-18 09:22:50 -07002827static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2828 struct attribute *attr, int index)
2829{
2830 struct device *dev = container_of(kobj, struct device, kobj);
2831 struct nct6775_data *data = dev_get_drvdata(dev);
2832 int pwm = index / 36; /* pwm index */
2833 int nr = index % 36; /* attribute index */
2834
2835 if (!(data->has_pwm & (1 << pwm)))
2836 return 0;
2837
2838 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2839 return 0;
2840 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2841 return 0;
2842 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2843 return 0;
2844
2845 if (nr >= 22 && nr <= 35) { /* auto point */
2846 int api = (nr - 22) / 2; /* auto point index */
2847
2848 if (api > data->auto_pwm_num)
2849 return 0;
2850 }
2851 return attr->mode;
2852}
2853
2854SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2855 show_fan_time, store_fan_time, 0, 0);
2856SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2857 show_fan_time, store_fan_time, 0, 1);
2858SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2859 show_fan_time, store_fan_time, 0, 2);
2860SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2861 store_pwm, 0, 1);
2862SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2863 store_pwm, 0, 2);
2864SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2865 show_temp_tolerance, store_temp_tolerance, 0, 0);
2866SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2867 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2868 0, 1);
2869
2870SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2871 0, 3);
2872
2873SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2874 store_pwm, 0, 4);
2875
2876SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2877 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2878SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2879 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2880
2881SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2882 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2883SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2884 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2885
2886SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2887 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2888SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2889 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2890
2891SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2892 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2893SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2894 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2895
2896SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2897 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2898SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2899 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2900
2901SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2902 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2903SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2904 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2905
2906SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2907 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2908SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2909 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2910
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002911/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002912 * nct6775_pwm_is_visible uses the index into the following array
2913 * to determine if attributes should be created or not.
2914 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002915 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002916static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2917 &sensor_dev_template_pwm,
2918 &sensor_dev_template_pwm_mode,
2919 &sensor_dev_template_pwm_enable,
2920 &sensor_dev_template_pwm_temp_sel,
2921 &sensor_dev_template_pwm_temp_tolerance,
2922 &sensor_dev_template_pwm_crit_temp_tolerance,
2923 &sensor_dev_template_pwm_target_temp,
2924 &sensor_dev_template_fan_target,
2925 &sensor_dev_template_fan_tolerance,
2926 &sensor_dev_template_pwm_stop_time,
2927 &sensor_dev_template_pwm_step_up_time,
2928 &sensor_dev_template_pwm_step_down_time,
2929 &sensor_dev_template_pwm_start,
2930 &sensor_dev_template_pwm_floor,
2931 &sensor_dev_template_pwm_weight_temp_sel,
2932 &sensor_dev_template_pwm_weight_temp_step,
2933 &sensor_dev_template_pwm_weight_temp_step_tol,
2934 &sensor_dev_template_pwm_weight_temp_step_base,
2935 &sensor_dev_template_pwm_weight_duty_step,
2936 &sensor_dev_template_pwm_max, /* 19 */
2937 &sensor_dev_template_pwm_step, /* 20 */
2938 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2939 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2940 &sensor_dev_template_pwm_auto_point1_temp,
2941 &sensor_dev_template_pwm_auto_point2_pwm,
2942 &sensor_dev_template_pwm_auto_point2_temp,
2943 &sensor_dev_template_pwm_auto_point3_pwm,
2944 &sensor_dev_template_pwm_auto_point3_temp,
2945 &sensor_dev_template_pwm_auto_point4_pwm,
2946 &sensor_dev_template_pwm_auto_point4_temp,
2947 &sensor_dev_template_pwm_auto_point5_pwm,
2948 &sensor_dev_template_pwm_auto_point5_temp,
2949 &sensor_dev_template_pwm_auto_point6_pwm,
2950 &sensor_dev_template_pwm_auto_point6_temp,
2951 &sensor_dev_template_pwm_auto_point7_pwm,
2952 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002953
Guenter Roeckf73cf632013-03-18 09:22:50 -07002954 NULL
2955};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002956
Guenter Roeckf73cf632013-03-18 09:22:50 -07002957static struct sensor_template_group nct6775_pwm_template_group = {
2958 .templates = nct6775_attributes_pwm_template,
2959 .is_visible = nct6775_pwm_is_visible,
2960 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002961};
2962
2963static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002964show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2965{
2966 struct nct6775_data *data = dev_get_drvdata(dev);
2967 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
2968}
2969
2970static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2971
Guenter Roecka6bd5872012-12-04 03:13:34 -08002972/* Case open detection */
2973
2974static ssize_t
2975clear_caseopen(struct device *dev, struct device_attribute *attr,
2976 const char *buf, size_t count)
2977{
2978 struct nct6775_data *data = dev_get_drvdata(dev);
2979 struct nct6775_sio_data *sio_data = dev->platform_data;
2980 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
2981 unsigned long val;
2982 u8 reg;
2983 int ret;
2984
2985 if (kstrtoul(buf, 10, &val) || val != 0)
2986 return -EINVAL;
2987
2988 mutex_lock(&data->update_lock);
2989
2990 /*
2991 * Use CR registers to clear caseopen status.
2992 * The CR registers are the same for all chips, and not all chips
2993 * support clearing the caseopen status through "regular" registers.
2994 */
2995 ret = superio_enter(sio_data->sioreg);
2996 if (ret) {
2997 count = ret;
2998 goto error;
2999 }
3000
3001 superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
3002 reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
3003 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
3004 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3005 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
3006 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3007 superio_exit(sio_data->sioreg);
3008
3009 data->valid = false; /* Force cache refresh */
3010error:
3011 mutex_unlock(&data->update_lock);
3012 return count;
3013}
3014
Guenter Roeckf73cf632013-03-18 09:22:50 -07003015static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3016 clear_caseopen, INTRUSION_ALARM_BASE);
3017static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3018 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003019static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3020 store_beep, INTRUSION_ALARM_BASE);
3021static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3022 store_beep, INTRUSION_ALARM_BASE + 1);
3023static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3024 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003025
3026static umode_t nct6775_other_is_visible(struct kobject *kobj,
3027 struct attribute *attr, int index)
3028{
3029 struct device *dev = container_of(kobj, struct device, kobj);
3030 struct nct6775_data *data = dev_get_drvdata(dev);
3031
3032 if (index == 1 && !data->have_vid)
3033 return 0;
3034
3035 if (index == 2 || index == 3) {
3036 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
3037 return 0;
3038 }
3039
Guenter Roeck30846992013-06-24 22:21:59 -07003040 if (index == 4 || index == 5) {
3041 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
3042 return 0;
3043 }
3044
Guenter Roeckf73cf632013-03-18 09:22:50 -07003045 return attr->mode;
3046}
3047
3048/*
3049 * nct6775_other_is_visible uses the index into the following array
3050 * to determine if attributes should be created or not.
3051 * Any change in order or content must be matched.
3052 */
3053static struct attribute *nct6775_attributes_other[] = {
3054 &dev_attr_name.attr,
3055 &dev_attr_cpu0_vid.attr, /* 1 */
3056 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
3057 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
Guenter Roeck30846992013-06-24 22:21:59 -07003058 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 4 */
3059 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 5 */
3060 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 6 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003061
3062 NULL
3063};
3064
3065static const struct attribute_group nct6775_group_other = {
3066 .attrs = nct6775_attributes_other,
3067 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003068};
3069
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003070/*
3071 * Driver and device management
3072 */
3073
3074static void nct6775_device_remove_files(struct device *dev)
3075{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003076 struct nct6775_data *data = dev_get_drvdata(dev);
3077
Guenter Roeckf73cf632013-03-18 09:22:50 -07003078 if (data->group_pwm)
3079 sysfs_remove_group(&dev->kobj, data->group_pwm);
3080 if (data->group_in)
3081 sysfs_remove_group(&dev->kobj, data->group_in);
3082 if (data->group_fan)
3083 sysfs_remove_group(&dev->kobj, data->group_fan);
3084 if (data->group_temp)
3085 sysfs_remove_group(&dev->kobj, data->group_temp);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003086
Guenter Roeckf73cf632013-03-18 09:22:50 -07003087 sysfs_remove_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003088}
3089
3090/* Get the monitoring functions started */
3091static inline void nct6775_init_device(struct nct6775_data *data)
3092{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003093 int i;
3094 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003095
3096 /* Start monitoring if needed */
3097 if (data->REG_CONFIG) {
3098 tmp = nct6775_read_value(data, data->REG_CONFIG);
3099 if (!(tmp & 0x01))
3100 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3101 }
3102
Guenter Roeckaa136e52012-12-04 03:26:05 -08003103 /* Enable temperature sensors if needed */
3104 for (i = 0; i < NUM_TEMP; i++) {
3105 if (!(data->have_temp & (1 << i)))
3106 continue;
3107 if (!data->reg_temp_config[i])
3108 continue;
3109 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3110 if (tmp & 0x01)
3111 nct6775_write_value(data, data->reg_temp_config[i],
3112 tmp & 0xfe);
3113 }
3114
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003115 /* Enable VBAT monitoring if needed */
3116 tmp = nct6775_read_value(data, data->REG_VBAT);
3117 if (!(tmp & 0x01))
3118 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003119
3120 diode = nct6775_read_value(data, data->REG_DIODE);
3121
3122 for (i = 0; i < data->temp_fixed_num; i++) {
3123 if (!(data->have_temp_fixed & (1 << i)))
3124 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003125 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3126 data->temp_type[i]
3127 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003128 else /* thermistor */
3129 data->temp_type[i] = 4;
3130 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003131}
3132
Guenter Roeckf73cf632013-03-18 09:22:50 -07003133static void
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003134nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
3135 struct nct6775_data *data)
3136{
3137 int regval;
3138 bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003139 bool pwm3pin, pwm4pin, pwm5pin;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003140
3141 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3142 if (data->kind == nct6775) {
3143 regval = superio_inb(sio_data->sioreg, 0x2c);
3144
3145 fan3pin = regval & (1 << 6);
3146 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003147 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003148
3149 /* On NCT6775, fan4 shares pins with the fdc interface */
3150 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
3151 fan4min = 0;
3152 fan5pin = 0;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003153 pwm4pin = 0;
3154 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003155 } else if (data->kind == nct6776) {
3156 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
3157
3158 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3159 regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
3160
3161 if (regval & 0x80)
3162 fan3pin = gpok;
3163 else
3164 fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
3165
3166 if (regval & 0x40)
3167 fan4pin = gpok;
3168 else
3169 fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
3170
3171 if (regval & 0x20)
3172 fan5pin = gpok;
3173 else
3174 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
3175
3176 fan4min = fan4pin;
3177 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003178 pwm3pin = fan3pin;
3179 pwm4pin = 0;
3180 pwm5pin = 0;
Guenter Roeck6c009502012-07-01 08:23:15 -07003181 } else if (data->kind == nct6106) {
3182 regval = superio_inb(sio_data->sioreg, 0x24);
3183 fan3pin = !(regval & 0x80);
3184 pwm3pin = regval & 0x08;
3185 fan3min = fan3pin;
3186
3187 fan4pin = false;
3188 fan4min = false;
3189 fan5pin = false;
3190 pwm4pin = false;
3191 pwm5pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003192 } else { /* NCT6779D */
3193 regval = superio_inb(sio_data->sioreg, 0x1c);
3194
3195 fan3pin = !(regval & (1 << 5));
3196 fan4pin = !(regval & (1 << 6));
3197 fan5pin = !(regval & (1 << 7));
3198
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003199 pwm3pin = !(regval & (1 << 0));
3200 pwm4pin = !(regval & (1 << 1));
3201 pwm5pin = !(regval & (1 << 2));
3202
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003203 fan3min = fan3pin;
3204 fan4min = fan4pin;
3205 }
3206
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003207 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
3208 data->has_fan |= fan3pin << 2;
3209 data->has_fan_min |= fan3min << 2;
3210
3211 data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
3212 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
3213
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003214 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003215}
3216
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003217static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3218 int *available, int *mask)
3219{
3220 int i;
3221 u8 src;
3222
3223 for (i = 0; i < data->pwm_num && *available; i++) {
3224 int index;
3225
3226 if (!regp[i])
3227 continue;
3228 src = nct6775_read_value(data, regp[i]);
3229 src &= 0x1f;
3230 if (!src || (*mask & (1 << src)))
3231 continue;
3232 if (src >= data->temp_label_num ||
3233 !strlen(data->temp_label[src]))
3234 continue;
3235
3236 index = __ffs(*available);
3237 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3238 *available &= ~(1 << index);
3239 *mask |= 1 << src;
3240 }
3241}
3242
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003243static int nct6775_probe(struct platform_device *pdev)
3244{
3245 struct device *dev = &pdev->dev;
3246 struct nct6775_sio_data *sio_data = dev->platform_data;
3247 struct nct6775_data *data;
3248 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003249 int i, s, err = 0;
3250 int src, mask, available;
3251 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3252 const u16 *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003253 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003254 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003255 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003256 struct attribute_group *group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003257
3258 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3259 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3260 DRVNAME))
3261 return -EBUSY;
3262
3263 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3264 GFP_KERNEL);
3265 if (!data)
3266 return -ENOMEM;
3267
3268 data->kind = sio_data->kind;
3269 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003270 mutex_init(&data->update_lock);
3271 data->name = nct6775_device_names[data->kind];
3272 data->bank = 0xff; /* Force initial bank selection */
3273 platform_set_drvdata(pdev, data);
3274
3275 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003276 case nct6106:
3277 data->in_num = 9;
3278 data->pwm_num = 3;
3279 data->auto_pwm_num = 4;
3280 data->temp_fixed_num = 3;
3281 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003282 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003283
3284 data->fan_from_reg = fan_from_reg13;
3285 data->fan_from_reg_min = fan_from_reg13;
3286
3287 data->temp_label = nct6776_temp_label;
3288 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3289
3290 data->REG_VBAT = NCT6106_REG_VBAT;
3291 data->REG_DIODE = NCT6106_REG_DIODE;
3292 data->DIODE_MASK = NCT6106_DIODE_MASK;
3293 data->REG_VIN = NCT6106_REG_IN;
3294 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3295 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3296 data->REG_TARGET = NCT6106_REG_TARGET;
3297 data->REG_FAN = NCT6106_REG_FAN;
3298 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3299 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3300 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3301 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3302 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3303 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3304 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3305 data->REG_PWM[0] = NCT6106_REG_PWM;
3306 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3307 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3308 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3309 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3310 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3311 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3312 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3313 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3314 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3315 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3316 data->REG_CRITICAL_TEMP_TOLERANCE
3317 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3318 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3319 data->CRITICAL_PWM_ENABLE_MASK
3320 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3321 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3322 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3323 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3324 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3325 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3326 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3327 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3328 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3329 data->REG_ALARM = NCT6106_REG_ALARM;
3330 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003331 data->REG_BEEP = NCT6106_REG_BEEP;
3332 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003333
3334 reg_temp = NCT6106_REG_TEMP;
3335 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3336 reg_temp_over = NCT6106_REG_TEMP_OVER;
3337 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3338 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3339 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3340 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003341 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3342 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003343
3344 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003345 case nct6775:
3346 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003347 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003348 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003349 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003350 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003351 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003352 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003353
3354 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003355 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003356
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003357 data->fan_from_reg = fan_from_reg16;
3358 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003359 data->target_temp_mask = 0x7f;
3360 data->tolerance_mask = 0x0f;
3361 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003362
Guenter Roeckaa136e52012-12-04 03:26:05 -08003363 data->temp_label = nct6775_temp_label;
3364 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3365
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003366 data->REG_CONFIG = NCT6775_REG_CONFIG;
3367 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003368 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003369 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003370 data->REG_VIN = NCT6775_REG_IN;
3371 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3372 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003373 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003374 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003375 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003376 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003377 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003378 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003379 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3380 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3381 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003382 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003383 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3384 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3385 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3386 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003387 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003388 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3389 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3390 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003391 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3392 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3393 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3394 data->REG_CRITICAL_TEMP_TOLERANCE
3395 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003396 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3397 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003398 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003399 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3400 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3401 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3402 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003403 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003404 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003405
3406 reg_temp = NCT6775_REG_TEMP;
3407 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3408 reg_temp_over = NCT6775_REG_TEMP_OVER;
3409 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3410 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3411 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3412 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3413
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003414 break;
3415 case nct6776:
3416 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003417 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003418 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003419 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003420 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003421 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003422 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003423
3424 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003425 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003426
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003427 data->fan_from_reg = fan_from_reg13;
3428 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003429 data->target_temp_mask = 0xff;
3430 data->tolerance_mask = 0x07;
3431 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003432
Guenter Roeckaa136e52012-12-04 03:26:05 -08003433 data->temp_label = nct6776_temp_label;
3434 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3435
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003436 data->REG_CONFIG = NCT6775_REG_CONFIG;
3437 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003438 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003439 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003440 data->REG_VIN = NCT6775_REG_IN;
3441 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3442 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003443 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003444 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003445 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003446 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003447 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003448 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003449 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3450 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3451 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3452 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003453 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003454 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3455 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003456 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3457 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003458 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3459 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3460 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003461 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3462 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3463 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3464 data->REG_CRITICAL_TEMP_TOLERANCE
3465 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003466 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3467 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003468 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003469 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3470 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3471 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3472 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003473 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003474 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003475
3476 reg_temp = NCT6775_REG_TEMP;
3477 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3478 reg_temp_over = NCT6775_REG_TEMP_OVER;
3479 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3480 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3481 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3482 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3483
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003484 break;
3485 case nct6779:
3486 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003487 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003488 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003489 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003490 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003491 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003492 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003493
3494 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003495 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003496
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003497 data->fan_from_reg = fan_from_reg13;
3498 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003499 data->target_temp_mask = 0xff;
3500 data->tolerance_mask = 0x07;
3501 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003502
Guenter Roeckaa136e52012-12-04 03:26:05 -08003503 data->temp_label = nct6779_temp_label;
3504 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3505
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003506 data->REG_CONFIG = NCT6775_REG_CONFIG;
3507 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003508 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003509 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003510 data->REG_VIN = NCT6779_REG_IN;
3511 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3512 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003513 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003514 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003515 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003516 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003517 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003518 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003519 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3520 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3521 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3522 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003523 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003524 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3525 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003526 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3527 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003528 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3529 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3530 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003531 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3532 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3533 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3534 data->REG_CRITICAL_TEMP_TOLERANCE
3535 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003536 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3537 data->CRITICAL_PWM_ENABLE_MASK
3538 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3539 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003540 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3541 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003542 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003543 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3544 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3545 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3546 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003547 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003548 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003549
3550 reg_temp = NCT6779_REG_TEMP;
3551 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3552 reg_temp_over = NCT6779_REG_TEMP_OVER;
3553 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3554 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3555 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3556 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3557
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003558 break;
3559 default:
3560 return -ENODEV;
3561 }
3562 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003563 data->have_temp = 0;
3564
3565 /*
3566 * On some boards, not all available temperature sources are monitored,
3567 * even though some of the monitoring registers are unused.
3568 * Get list of unused monitoring registers, then detect if any fan
3569 * controls are configured to use unmonitored temperature sources.
3570 * If so, assign the unmonitored temperature sources to available
3571 * monitoring registers.
3572 */
3573 mask = 0;
3574 available = 0;
3575 for (i = 0; i < num_reg_temp; i++) {
3576 if (reg_temp[i] == 0)
3577 continue;
3578
3579 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3580 if (!src || (mask & (1 << src)))
3581 available |= 1 << i;
3582
3583 mask |= 1 << src;
3584 }
3585
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003586 /*
3587 * Now find unmonitored temperature registers and enable monitoring
3588 * if additional monitoring registers are available.
3589 */
3590 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3591 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3592
Guenter Roeckaa136e52012-12-04 03:26:05 -08003593 mask = 0;
3594 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3595 for (i = 0; i < num_reg_temp; i++) {
3596 if (reg_temp[i] == 0)
3597 continue;
3598
3599 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3600 if (!src || (mask & (1 << src)))
3601 continue;
3602
3603 if (src >= data->temp_label_num ||
3604 !strlen(data->temp_label[src])) {
3605 dev_info(dev,
3606 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3607 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3608 continue;
3609 }
3610
3611 mask |= 1 << src;
3612
3613 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3614 if (src <= data->temp_fixed_num) {
3615 data->have_temp |= 1 << (src - 1);
3616 data->have_temp_fixed |= 1 << (src - 1);
3617 data->reg_temp[0][src - 1] = reg_temp[i];
3618 data->reg_temp[1][src - 1] = reg_temp_over[i];
3619 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003620 if (reg_temp_crit_h && reg_temp_crit_h[i])
3621 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3622 else if (reg_temp_crit[src - 1])
3623 data->reg_temp[3][src - 1]
3624 = reg_temp_crit[src - 1];
3625 if (reg_temp_crit_l && reg_temp_crit_l[i])
3626 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003627 data->reg_temp_config[src - 1] = reg_temp_config[i];
3628 data->temp_src[src - 1] = src;
3629 continue;
3630 }
3631
3632 if (s >= NUM_TEMP)
3633 continue;
3634
3635 /* Use dynamic index for other sources */
3636 data->have_temp |= 1 << s;
3637 data->reg_temp[0][s] = reg_temp[i];
3638 data->reg_temp[1][s] = reg_temp_over[i];
3639 data->reg_temp[2][s] = reg_temp_hyst[i];
3640 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003641 if (reg_temp_crit_h && reg_temp_crit_h[i])
3642 data->reg_temp[3][s] = reg_temp_crit_h[i];
3643 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003644 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003645 if (reg_temp_crit_l && reg_temp_crit_l[i])
3646 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003647
3648 data->temp_src[s] = src;
3649 s++;
3650 }
3651
3652#ifdef USE_ALTERNATE
3653 /*
3654 * Go through the list of alternate temp registers and enable
3655 * if possible.
3656 * The temperature is already monitored if the respective bit in <mask>
3657 * is set.
3658 */
3659 for (i = 0; i < data->temp_label_num - 1; i++) {
3660 if (!reg_temp_alternate[i])
3661 continue;
3662 if (mask & (1 << (i + 1)))
3663 continue;
3664 if (i < data->temp_fixed_num) {
3665 if (data->have_temp & (1 << i))
3666 continue;
3667 data->have_temp |= 1 << i;
3668 data->have_temp_fixed |= 1 << i;
3669 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05cd2013-05-09 10:40:01 -07003670 if (i < num_reg_temp) {
3671 data->reg_temp[1][i] = reg_temp_over[i];
3672 data->reg_temp[2][i] = reg_temp_hyst[i];
3673 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003674 data->temp_src[i] = i + 1;
3675 continue;
3676 }
3677
3678 if (s >= NUM_TEMP) /* Abort if no more space */
3679 break;
3680
3681 data->have_temp |= 1 << s;
3682 data->reg_temp[0][s] = reg_temp_alternate[i];
3683 data->temp_src[s] = i + 1;
3684 s++;
3685 }
3686#endif /* USE_ALTERNATE */
3687
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003688 /* Initialize the chip */
3689 nct6775_init_device(data);
3690
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003691 err = superio_enter(sio_data->sioreg);
3692 if (err)
3693 return err;
3694
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003695 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3696 switch (data->kind) {
3697 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003698 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003699 break;
3700 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003701 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003702 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003703 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003704 case nct6779:
3705 break;
3706 }
3707
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003708 /*
3709 * Read VID value
3710 * We can get the VID input values directly at logical device D 0xe3.
3711 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003712 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003713 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3714 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3715 data->vrm = vid_which_vrm();
3716 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003717
3718 if (fan_debounce) {
3719 u8 tmp;
3720
3721 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3722 tmp = superio_inb(sio_data->sioreg,
3723 NCT6775_REG_CR_FAN_DEBOUNCE);
3724 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003725 case nct6106:
3726 tmp |= 0xe0;
3727 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003728 case nct6775:
3729 tmp |= 0x1e;
3730 break;
3731 case nct6776:
3732 case nct6779:
3733 tmp |= 0x3e;
3734 break;
3735 }
3736 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3737 tmp);
3738 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3739 data->name);
3740 }
3741
Guenter Roeckf73cf632013-03-18 09:22:50 -07003742 nct6775_check_fan_inputs(sio_data, data);
3743
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003744 superio_exit(sio_data->sioreg);
3745
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003746 /* Read fan clock dividers immediately */
3747 nct6775_init_fan_common(dev, data);
3748
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003749 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003750 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3751 data->pwm_num);
3752 if (IS_ERR(group)) {
3753 err = PTR_ERR(group);
3754 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003755 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003756 data->group_pwm = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003757
Guenter Roeckf73cf632013-03-18 09:22:50 -07003758 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3759 fls(data->have_in));
3760 if (IS_ERR(group)) {
3761 err = PTR_ERR(group);
3762 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003763 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003764 data->group_in = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003765
Guenter Roeckf73cf632013-03-18 09:22:50 -07003766 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3767 fls(data->has_fan));
3768 if (IS_ERR(group)) {
3769 err = PTR_ERR(group);
3770 goto exit_remove;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003771 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003772 data->group_fan = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003773
Guenter Roeckf73cf632013-03-18 09:22:50 -07003774 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3775 fls(data->have_temp));
3776 if (IS_ERR(group)) {
3777 err = PTR_ERR(group);
3778 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003779 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003780 data->group_temp = group;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003781
Guenter Roeckf73cf632013-03-18 09:22:50 -07003782 err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003783 if (err)
3784 goto exit_remove;
3785
3786 data->hwmon_dev = hwmon_device_register(dev);
3787 if (IS_ERR(data->hwmon_dev)) {
3788 err = PTR_ERR(data->hwmon_dev);
3789 goto exit_remove;
3790 }
3791
3792 return 0;
3793
3794exit_remove:
3795 nct6775_device_remove_files(dev);
3796 return err;
3797}
3798
3799static int nct6775_remove(struct platform_device *pdev)
3800{
3801 struct nct6775_data *data = platform_get_drvdata(pdev);
3802
3803 hwmon_device_unregister(data->hwmon_dev);
3804 nct6775_device_remove_files(&pdev->dev);
3805
3806 return 0;
3807}
3808
Guenter Roeck84d19d92012-12-04 08:01:39 -08003809#ifdef CONFIG_PM
3810static int nct6775_suspend(struct device *dev)
3811{
3812 struct nct6775_data *data = nct6775_update_device(dev);
3813 struct nct6775_sio_data *sio_data = dev->platform_data;
3814
3815 mutex_lock(&data->update_lock);
3816 data->vbat = nct6775_read_value(data, data->REG_VBAT);
3817 if (sio_data->kind == nct6775) {
3818 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3819 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3820 }
3821 mutex_unlock(&data->update_lock);
3822
3823 return 0;
3824}
3825
3826static int nct6775_resume(struct device *dev)
3827{
3828 struct nct6775_data *data = dev_get_drvdata(dev);
3829 struct nct6775_sio_data *sio_data = dev->platform_data;
3830 int i, j;
3831
3832 mutex_lock(&data->update_lock);
3833 data->bank = 0xff; /* Force initial bank selection */
3834
3835 /* Restore limits */
3836 for (i = 0; i < data->in_num; i++) {
3837 if (!(data->have_in & (1 << i)))
3838 continue;
3839
3840 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3841 data->in[i][1]);
3842 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3843 data->in[i][2]);
3844 }
3845
Guenter Roeckc409fd42013-04-09 05:04:00 -07003846 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003847 if (!(data->has_fan_min & (1 << i)))
3848 continue;
3849
3850 nct6775_write_value(data, data->REG_FAN_MIN[i],
3851 data->fan_min[i]);
3852 }
3853
3854 for (i = 0; i < NUM_TEMP; i++) {
3855 if (!(data->have_temp & (1 << i)))
3856 continue;
3857
Guenter Roeckc409fd42013-04-09 05:04:00 -07003858 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003859 if (data->reg_temp[j][i])
3860 nct6775_write_temp(data, data->reg_temp[j][i],
3861 data->temp[j][i]);
3862 }
3863
3864 /* Restore other settings */
3865 nct6775_write_value(data, data->REG_VBAT, data->vbat);
3866 if (sio_data->kind == nct6775) {
3867 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3868 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3869 }
3870
3871 /* Force re-reading all values */
3872 data->valid = false;
3873 mutex_unlock(&data->update_lock);
3874
3875 return 0;
3876}
3877
3878static const struct dev_pm_ops nct6775_dev_pm_ops = {
3879 .suspend = nct6775_suspend,
3880 .resume = nct6775_resume,
3881};
3882
3883#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
3884#else
3885#define NCT6775_DEV_PM_OPS NULL
3886#endif /* CONFIG_PM */
3887
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003888static struct platform_driver nct6775_driver = {
3889 .driver = {
3890 .owner = THIS_MODULE,
3891 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08003892 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003893 },
3894 .probe = nct6775_probe,
3895 .remove = nct6775_remove,
3896};
3897
Guenter Roeck6d4b3622013-04-21 09:08:11 -07003898static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07003899 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07003900 "NCT6775F",
3901 "NCT6776D/F",
3902 "NCT6779D",
3903};
3904
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003905/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003906static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003907{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003908 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003909 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003910 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003911
3912 err = superio_enter(sioaddr);
3913 if (err)
3914 return err;
3915
3916 if (force_id)
3917 val = force_id;
3918 else
3919 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
3920 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
3921 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003922 case SIO_NCT6106_ID:
3923 sio_data->kind = nct6106;
3924 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003925 case SIO_NCT6775_ID:
3926 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003927 break;
3928 case SIO_NCT6776_ID:
3929 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003930 break;
3931 case SIO_NCT6779_ID:
3932 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003933 break;
3934 default:
3935 if (val != 0xffff)
3936 pr_debug("unsupported chip ID: 0x%04x\n", val);
3937 superio_exit(sioaddr);
3938 return -ENODEV;
3939 }
3940
3941 /* We have a known chip, find the HWM I/O address */
3942 superio_select(sioaddr, NCT6775_LD_HWM);
3943 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
3944 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07003945 addr = val & IOREGION_ALIGNMENT;
3946 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003947 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
3948 superio_exit(sioaddr);
3949 return -ENODEV;
3950 }
3951
3952 /* Activate logical device if needed */
3953 val = superio_inb(sioaddr, SIO_REG_ENABLE);
3954 if (!(val & 0x01)) {
3955 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
3956 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
3957 }
3958
3959 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07003960 pr_info("Found %s or compatible chip at %#x:%#x\n",
3961 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003962 sio_data->sioreg = sioaddr;
3963
Guenter Roeck698a7c22013-04-05 07:35:25 -07003964 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003965}
3966
3967/*
3968 * when Super-I/O functions move to a separate file, the Super-I/O
3969 * bus will manage the lifetime of the device and this module will only keep
3970 * track of the nct6775 driver. But since we platform_device_alloc(), we
3971 * must keep track of the device
3972 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003973static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003974
3975static int __init sensors_nct6775_init(void)
3976{
Guenter Roeck698a7c22013-04-05 07:35:25 -07003977 int i, err;
3978 bool found = false;
3979 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003980 struct resource res;
3981 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003982 int sioaddr[2] = { 0x2e, 0x4e };
3983
3984 err = platform_driver_register(&nct6775_driver);
3985 if (err)
3986 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003987
3988 /*
3989 * initialize sio_data->kind and sio_data->sioreg.
3990 *
3991 * when Super-I/O functions move to a separate file, the Super-I/O
3992 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
3993 * nct6775 hardware monitor, and call probe()
3994 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003995 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3996 address = nct6775_find(sioaddr[i], &sio_data);
3997 if (address <= 0)
3998 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003999
Guenter Roeck698a7c22013-04-05 07:35:25 -07004000 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004001
Guenter Roeck698a7c22013-04-05 07:35:25 -07004002 pdev[i] = platform_device_alloc(DRVNAME, address);
4003 if (!pdev[i]) {
4004 err = -ENOMEM;
4005 goto exit_device_put;
4006 }
4007
4008 err = platform_device_add_data(pdev[i], &sio_data,
4009 sizeof(struct nct6775_sio_data));
4010 if (err)
4011 goto exit_device_put;
4012
4013 memset(&res, 0, sizeof(res));
4014 res.name = DRVNAME;
4015 res.start = address + IOREGION_OFFSET;
4016 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4017 res.flags = IORESOURCE_IO;
4018
4019 err = acpi_check_resource_conflict(&res);
4020 if (err) {
4021 platform_device_put(pdev[i]);
4022 pdev[i] = NULL;
4023 continue;
4024 }
4025
4026 err = platform_device_add_resources(pdev[i], &res, 1);
4027 if (err)
4028 goto exit_device_put;
4029
4030 /* platform_device_add calls probe() */
4031 err = platform_device_add(pdev[i]);
4032 if (err)
4033 goto exit_device_put;
4034 }
4035 if (!found) {
4036 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004037 goto exit_unregister;
4038 }
4039
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004040 return 0;
4041
4042exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07004043 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4044 if (pdev[i])
4045 platform_device_put(pdev[i]);
4046 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004047exit_unregister:
4048 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004049 return err;
4050}
4051
4052static void __exit sensors_nct6775_exit(void)
4053{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004054 int i;
4055
4056 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4057 if (pdev[i])
4058 platform_device_unregister(pdev[i]);
4059 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004060 platform_driver_unregister(&nct6775_driver);
4061}
4062
4063MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4064MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4065MODULE_LICENSE("GPL");
4066
4067module_init(sensors_nct6775_init);
4068module_exit(sensors_nct6775_exit);