blob: bebddbbd39074f04722e0251eb2049f650eea553 [file] [log] [blame]
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001/*
2 * nct6775 - Driver for the hardware monitoring functionality of
3 * Nuvoton NCT677x Super-I/O chips
4 *
5 * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
6 *
7 * Derived from w83627ehf driver
8 * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org>
9 * Copyright (C) 2006 Yuan Mu (Winbond),
10 * Rudolf Marek <r.marek@assembler.cz>
11 * David Hubbard <david.c.hubbard@gmail.com>
12 * Daniel J Blueman <daniel.blueman@gmail.com>
13 * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
14 *
15 * Shamelessly ripped from the w83627hf driver
16 * Copyright (C) 2003 Mark Studebaker
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 *
33 * Supports the following chips:
34 *
35 * Chip #vin #fan #pwm #temp chip IDs man ID
Guenter Roeck6c009502012-07-01 08:23:15 -070036 * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070037 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
40 *
41 * #temp lists the number of monitored temperature sources (first value) plus
42 * the number of directly connectable temperature sensors (second value).
43 */
44
45#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46
47#include <linux/module.h>
48#include <linux/init.h>
49#include <linux/slab.h>
50#include <linux/jiffies.h>
51#include <linux/platform_device.h>
52#include <linux/hwmon.h>
53#include <linux/hwmon-sysfs.h>
54#include <linux/hwmon-vid.h>
55#include <linux/err.h>
56#include <linux/mutex.h>
57#include <linux/acpi.h>
58#include <linux/io.h>
59#include "lm75.h"
60
Guenter Roeckaa136e52012-12-04 03:26:05 -080061#define USE_ALTERNATE
62
Guenter Roeck6c009502012-07-01 08:23:15 -070063enum kinds { nct6106, nct6775, nct6776, nct6779 };
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070064
65/* used to set data->name = nct6775_device_names[data->sio_kind] */
66static const char * const nct6775_device_names[] = {
Guenter Roeck6c009502012-07-01 08:23:15 -070067 "nct6106",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070068 "nct6775",
69 "nct6776",
70 "nct6779",
71};
72
73static unsigned short force_id;
74module_param(force_id, ushort, 0);
75MODULE_PARM_DESC(force_id, "Override the detected device ID");
76
Guenter Roeck47ece962012-12-04 07:59:32 -080077static unsigned short fan_debounce;
78module_param(fan_debounce, ushort, 0);
79MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
80
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070081#define DRVNAME "nct6775"
82
83/*
84 * Super-I/O constants and functions
85 */
86
Guenter Roecka6bd5872012-12-04 03:13:34 -080087#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070088#define NCT6775_LD_HWM 0x0b
89#define NCT6775_LD_VID 0x0d
90
91#define SIO_REG_LDSEL 0x07 /* Logical device select */
92#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
93#define SIO_REG_ENABLE 0x30 /* Logical device enable */
94#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
95
Guenter Roeck6c009502012-07-01 08:23:15 -070096#define SIO_NCT6106_ID 0xc450
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070097#define SIO_NCT6775_ID 0xb470
98#define SIO_NCT6776_ID 0xc330
99#define SIO_NCT6779_ID 0xc560
100#define SIO_ID_MASK 0xFFF0
101
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800102enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
103
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700104static inline void
105superio_outb(int ioreg, int reg, int val)
106{
107 outb(reg, ioreg);
108 outb(val, ioreg + 1);
109}
110
111static inline int
112superio_inb(int ioreg, int reg)
113{
114 outb(reg, ioreg);
115 return inb(ioreg + 1);
116}
117
118static inline void
119superio_select(int ioreg, int ld)
120{
121 outb(SIO_REG_LDSEL, ioreg);
122 outb(ld, ioreg + 1);
123}
124
125static inline int
126superio_enter(int ioreg)
127{
128 /*
129 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
130 */
131 if (!request_muxed_region(ioreg, 2, DRVNAME))
132 return -EBUSY;
133
134 outb(0x87, ioreg);
135 outb(0x87, ioreg);
136
137 return 0;
138}
139
140static inline void
141superio_exit(int ioreg)
142{
143 outb(0xaa, ioreg);
144 outb(0x02, ioreg);
145 outb(0x02, ioreg + 1);
146 release_region(ioreg, 2);
147}
148
149/*
150 * ISA constants
151 */
152
153#define IOREGION_ALIGNMENT (~7)
154#define IOREGION_OFFSET 5
155#define IOREGION_LENGTH 2
156#define ADDR_REG_OFFSET 0
157#define DATA_REG_OFFSET 1
158
159#define NCT6775_REG_BANK 0x4E
160#define NCT6775_REG_CONFIG 0x40
161
162/*
163 * Not currently used:
164 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
165 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
166 * REG_MAN_ID is at port 0x4f
167 * REG_CHIP_ID is at port 0x58
168 */
169
Guenter Roeckaa136e52012-12-04 03:26:05 -0800170#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
171#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
172
Guenter Roeck6c009502012-07-01 08:23:15 -0700173#define NUM_REG_ALARM 7 /* Max number of alarm registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700174
175/* Common and NCT6775 specific data */
176
177/* Voltage min/max registers for nr=7..14 are in bank 5 */
178
179static const u16 NCT6775_REG_IN_MAX[] = {
180 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
181 0x55c, 0x55e, 0x560, 0x562 };
182static const u16 NCT6775_REG_IN_MIN[] = {
183 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
184 0x55d, 0x55f, 0x561, 0x563 };
185static const u16 NCT6775_REG_IN[] = {
186 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
187};
188
189#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800190#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700191#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700192
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800193#define NCT6775_REG_FANDIV1 0x506
194#define NCT6775_REG_FANDIV2 0x507
195
Guenter Roeck47ece962012-12-04 07:59:32 -0800196#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
197
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700198static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
199
200/* 0..15 voltages, 16..23 fans, 24..31 temperatures */
201
202static const s8 NCT6775_ALARM_BITS[] = {
203 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
204 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
205 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700206 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700207 -1, -1, -1, /* unused */
208 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
209 12, -1 }; /* intrusion0, intrusion1 */
210
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800211#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800212#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800213#define INTRUSION_ALARM_BASE 30
214
215static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
216static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
217
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800218/* DC or PWM output fan configuration */
219static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
220static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
221
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800222/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800223
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800224static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
225static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
226static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
227 0x103, 0x203, 0x303, 0x803, 0x903 };
228static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
229 0x104, 0x204, 0x304, 0x804, 0x904 };
230static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
231 0x105, 0x205, 0x305, 0x805, 0x905 };
232static const u16 NCT6775_REG_FAN_START_OUTPUT[]
233 = { 0x106, 0x206, 0x306, 0x806, 0x906 };
234static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
235static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
236
237static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
238 0x107, 0x207, 0x307, 0x807, 0x907 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800239static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
240static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
241
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800242static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
243static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800244static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700245static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800246
Guenter Roeckaa136e52012-12-04 03:26:05 -0800247static const u16 NCT6775_REG_TEMP[] = {
248 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
249
250static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
251 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
252static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
253 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
254static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
255 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
256
257static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
258 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
259
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800260static const u16 NCT6775_REG_TEMP_SEL[] = {
261 0x100, 0x200, 0x300, 0x800, 0x900 };
262
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800263static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
264 0x139, 0x239, 0x339, 0x839, 0x939 };
265static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
266 0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
267static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
268 0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
269static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
270 0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
271static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
272 0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
273
Guenter Roeckaa136e52012-12-04 03:26:05 -0800274static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
275
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800276static const u16 NCT6775_REG_AUTO_TEMP[] = {
277 0x121, 0x221, 0x321, 0x821, 0x921 };
278static const u16 NCT6775_REG_AUTO_PWM[] = {
279 0x127, 0x227, 0x327, 0x827, 0x927 };
280
281#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
282#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
283
284static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
285
286static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
287 0x135, 0x235, 0x335, 0x835, 0x935 };
288static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
289 0x138, 0x238, 0x338, 0x838, 0x938 };
290
Guenter Roeckaa136e52012-12-04 03:26:05 -0800291static const char *const nct6775_temp_label[] = {
292 "",
293 "SYSTIN",
294 "CPUTIN",
295 "AUXTIN",
296 "AMD SB-TSI",
297 "PECI Agent 0",
298 "PECI Agent 1",
299 "PECI Agent 2",
300 "PECI Agent 3",
301 "PECI Agent 4",
302 "PECI Agent 5",
303 "PECI Agent 6",
304 "PECI Agent 7",
305 "PCH_CHIP_CPU_MAX_TEMP",
306 "PCH_CHIP_TEMP",
307 "PCH_CPU_TEMP",
308 "PCH_MCH_TEMP",
309 "PCH_DIM0_TEMP",
310 "PCH_DIM1_TEMP",
311 "PCH_DIM2_TEMP",
312 "PCH_DIM3_TEMP"
313};
314
315static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
316 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
317
318static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
319 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
320 0xa07 };
321
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700322/* NCT6776 specific data */
323
324static const s8 NCT6776_ALARM_BITS[] = {
325 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
326 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
327 -1, /* unused */
328 6, 7, 11, 10, 23, /* fan1..fan5 */
329 -1, -1, -1, /* unused */
330 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
331 12, 9 }; /* intrusion0, intrusion1 */
332
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800333static const u16 NCT6776_REG_TOLERANCE_H[] = {
334 0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
335
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800336static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
337static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
338
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800339static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800340static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800341
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800342static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
343 0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
344
Guenter Roeckaa136e52012-12-04 03:26:05 -0800345static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
346 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
347
348static const char *const nct6776_temp_label[] = {
349 "",
350 "SYSTIN",
351 "CPUTIN",
352 "AUXTIN",
353 "SMBUSMASTER 0",
354 "SMBUSMASTER 1",
355 "SMBUSMASTER 2",
356 "SMBUSMASTER 3",
357 "SMBUSMASTER 4",
358 "SMBUSMASTER 5",
359 "SMBUSMASTER 6",
360 "SMBUSMASTER 7",
361 "PECI Agent 0",
362 "PECI Agent 1",
363 "PCH_CHIP_CPU_MAX_TEMP",
364 "PCH_CHIP_TEMP",
365 "PCH_CPU_TEMP",
366 "PCH_MCH_TEMP",
367 "PCH_DIM0_TEMP",
368 "PCH_DIM1_TEMP",
369 "PCH_DIM2_TEMP",
370 "PCH_DIM3_TEMP",
371 "BYTE_TEMP"
372};
373
374static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
375 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
376
377static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
378 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
379
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700380/* NCT6779 specific data */
381
382static const u16 NCT6779_REG_IN[] = {
383 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
384 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
385
386static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
387 0x459, 0x45A, 0x45B, 0x568 };
388
389static const s8 NCT6779_ALARM_BITS[] = {
390 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
391 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
392 -1, /* unused */
393 6, 7, 11, 10, 23, /* fan1..fan5 */
394 -1, -1, -1, /* unused */
395 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
396 12, 9 }; /* intrusion0, intrusion1 */
397
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800398static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800399static const u16 NCT6779_REG_FAN_PULSES[] = {
400 0x644, 0x645, 0x646, 0x647, 0x648 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800401
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800402static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
403 0x136, 0x236, 0x336, 0x836, 0x936 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700404#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800405static const u16 NCT6779_REG_CRITICAL_PWM[] = {
406 0x137, 0x237, 0x337, 0x837, 0x937 };
407
Guenter Roeckaa136e52012-12-04 03:26:05 -0800408static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
409static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
410 0x18, 0x152 };
411static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
412 0x3a, 0x153 };
413static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
414 0x39, 0x155 };
415
416static const u16 NCT6779_REG_TEMP_OFFSET[] = {
417 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
418
419static const char *const nct6779_temp_label[] = {
420 "",
421 "SYSTIN",
422 "CPUTIN",
423 "AUXTIN0",
424 "AUXTIN1",
425 "AUXTIN2",
426 "AUXTIN3",
427 "",
428 "SMBUSMASTER 0",
429 "SMBUSMASTER 1",
430 "SMBUSMASTER 2",
431 "SMBUSMASTER 3",
432 "SMBUSMASTER 4",
433 "SMBUSMASTER 5",
434 "SMBUSMASTER 6",
435 "SMBUSMASTER 7",
436 "PECI Agent 0",
437 "PECI Agent 1",
438 "PCH_CHIP_CPU_MAX_TEMP",
439 "PCH_CHIP_TEMP",
440 "PCH_CPU_TEMP",
441 "PCH_MCH_TEMP",
442 "PCH_DIM0_TEMP",
443 "PCH_DIM1_TEMP",
444 "PCH_DIM2_TEMP",
445 "PCH_DIM3_TEMP",
446 "BYTE_TEMP"
447};
448
449static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
450 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
451 0, 0, 0, 0, 0, 0, 0, 0,
452 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
453 0x408, 0 };
454
455static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
456 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
457
Guenter Roeck6c009502012-07-01 08:23:15 -0700458/* NCT6102D/NCT6106D specific data */
459
460#define NCT6106_REG_VBAT 0x318
461#define NCT6106_REG_DIODE 0x319
462#define NCT6106_DIODE_MASK 0x01
463
464static const u16 NCT6106_REG_IN_MAX[] = {
465 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
466static const u16 NCT6106_REG_IN_MIN[] = {
467 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
468static const u16 NCT6106_REG_IN[] = {
469 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
470
471static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
472static const u16 NCT6106_REG_TEMP_HYST[] = {
473 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
474static const u16 NCT6106_REG_TEMP_OVER[] = {
475 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd4 };
476static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
477static const u16 NCT6106_REG_TEMP_CONFIG[] = {
478 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
479
480static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
481static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
482static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
483static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
484
485static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
486static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
487static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
488static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
489static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
490static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
491static const u16 NCT6106_REG_TEMP_SOURCE[] = {
492 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
493
494static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
495static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
496 0x11b, 0x12b, 0x13b };
497
498static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
499#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
500static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
501
502static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
503static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
504static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
505static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
506static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
507static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
508
509static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
510
511static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
512static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
513static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
514static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
515static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
516static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
517
518static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
519static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
520
521static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
522 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
523
524static const s8 NCT6106_ALARM_BITS[] = {
525 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
526 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
527 -1, /* unused */
528 32, 33, 34, -1, -1, /* fan1..fan5 */
529 -1, -1, -1, /* unused */
530 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
531 48, -1 /* intrusion0, intrusion1 */
532};
533
534static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
535 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
536
537static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
538 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
539
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800540static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
541{
542 if (mode == 0 && pwm == 255)
543 return off;
544 return mode + 1;
545}
546
547static int pwm_enable_to_reg(enum pwm_enable mode)
548{
549 if (mode == off)
550 return 0;
551 return mode - 1;
552}
553
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700554/*
555 * Conversions
556 */
557
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800558/* 1 is DC mode, output in ms */
559static unsigned int step_time_from_reg(u8 reg, u8 mode)
560{
561 return mode ? 400 * reg : 100 * reg;
562}
563
564static u8 step_time_to_reg(unsigned int msec, u8 mode)
565{
566 return clamp_val((mode ? (msec + 200) / 400 :
567 (msec + 50) / 100), 1, 255);
568}
569
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800570static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
571{
572 if (reg == 0 || reg == 255)
573 return 0;
574 return 1350000U / (reg << divreg);
575}
576
577static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
578{
579 if ((reg & 0xff1f) == 0xff1f)
580 return 0;
581
582 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
583
584 if (reg == 0)
585 return 0;
586
587 return 1350000U / reg;
588}
589
590static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
591{
592 if (reg == 0 || reg == 0xffff)
593 return 0;
594
595 /*
596 * Even though the registers are 16 bit wide, the fan divisor
597 * still applies.
598 */
599 return 1350000U / (reg << divreg);
600}
601
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800602static u16 fan_to_reg(u32 fan, unsigned int divreg)
603{
604 if (!fan)
605 return 0;
606
607 return (1350000U / fan) >> divreg;
608}
609
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800610static inline unsigned int
611div_from_reg(u8 reg)
612{
613 return 1 << reg;
614}
615
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700616/*
617 * Some of the voltage inputs have internal scaling, the tables below
618 * contain 8 (the ADC LSB in mV) * scaling factor * 100
619 */
620static const u16 scale_in[15] = {
621 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
622 800, 800
623};
624
625static inline long in_from_reg(u8 reg, u8 nr)
626{
627 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
628}
629
630static inline u8 in_to_reg(u32 val, u8 nr)
631{
632 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
633}
634
635/*
636 * Data structures and manipulation thereof
637 */
638
639struct nct6775_data {
640 int addr; /* IO base of hw monitor block */
641 enum kinds kind;
642 const char *name;
643
644 struct device *hwmon_dev;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700645 struct attribute_group *group_in;
646 struct attribute_group *group_fan;
647 struct attribute_group *group_temp;
648 struct attribute_group *group_pwm;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700649
Guenter Roeckaa136e52012-12-04 03:26:05 -0800650 u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
651 * 3=temp_crit
652 */
653 u8 temp_src[NUM_TEMP];
654 u16 reg_temp_config[NUM_TEMP];
655 const char * const *temp_label;
656 int temp_label_num;
657
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700658 u16 REG_CONFIG;
659 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800660 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700661 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700662
663 const s8 *ALARM_BITS;
664
665 const u16 *REG_VIN;
666 const u16 *REG_IN_MINMAX[2];
667
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800668 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800669 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800670 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800671 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800672 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700673 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800674 const u16 *REG_FAN_TIME[3];
675
676 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800677
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800678 const u8 *REG_PWM_MODE;
679 const u8 *PWM_MODE_MASK;
680
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800681 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
682 * [3]=pwm_max, [4]=pwm_step,
683 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800684 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800685 const u16 *REG_PWM_READ;
686
Guenter Roeck6c009502012-07-01 08:23:15 -0700687 const u16 *REG_CRITICAL_PWM_ENABLE;
688 u8 CRITICAL_PWM_ENABLE_MASK;
689 const u16 *REG_CRITICAL_PWM;
690
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800691 const u16 *REG_AUTO_TEMP;
692 const u16 *REG_AUTO_PWM;
693
694 const u16 *REG_CRITICAL_TEMP;
695 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
696
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800697 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800698 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800699 const u16 *REG_WEIGHT_TEMP_SEL;
700 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
701
Guenter Roeckaa136e52012-12-04 03:26:05 -0800702 const u16 *REG_TEMP_OFFSET;
703
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700704 const u16 *REG_ALARM;
705
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800706 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
707 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
708
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700709 struct mutex update_lock;
710 bool valid; /* true if following fields are valid */
711 unsigned long last_updated; /* In jiffies */
712
713 /* Register values */
714 u8 bank; /* current register bank */
715 u8 in_num; /* number of in inputs we have */
716 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800717 unsigned int rpm[5];
718 u16 fan_min[5];
Guenter Roeck5c25d952012-12-11 07:29:06 -0800719 u8 fan_pulses[5];
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800720 u8 fan_div[5];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800721 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800722 u8 has_fan; /* some fan inputs can be disabled */
723 u8 has_fan_min; /* some fans don't have min register */
724 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700725
Guenter Roeck6c009502012-07-01 08:23:15 -0700726 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800727 u8 temp_fixed_num; /* 3 or 6 */
728 u8 temp_type[NUM_TEMP_FIXED];
729 s8 temp_offset[NUM_TEMP_FIXED];
730 s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
731 * 3=temp_crit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700732 u64 alarms;
733
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800734 u8 pwm_num; /* number of pwm */
735 u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
736 enum pwm_enable pwm_enable[5];
737 /* 0->off
738 * 1->manual
739 * 2->thermal cruise mode (also called SmartFan I)
740 * 3->fan speed cruise mode
741 * 4->SmartFan III
742 * 5->enhanced variable thermal cruise (SmartFan IV)
743 */
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800744 u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
745 * [3]=pwm_max, [4]=pwm_step,
746 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800747 */
748
749 u8 target_temp[5];
750 u8 target_temp_mask;
751 u32 target_speed[5];
752 u32 target_speed_tolerance[5];
753 u8 speed_tolerance_limit;
754
755 u8 temp_tolerance[2][5];
756 u8 tolerance_mask;
757
758 u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
759
760 /* Automatic fan speed control registers */
761 int auto_pwm_num;
762 u8 auto_pwm[5][7];
763 u8 auto_temp[5][7];
764 u8 pwm_temp_sel[5];
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800765 u8 pwm_weight_temp_sel[5];
766 u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol,
767 * 2->temp_base
768 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800769
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700770 u8 vid;
771 u8 vrm;
772
Guenter Roeckf73cf632013-03-18 09:22:50 -0700773 bool have_vid;
774
Guenter Roeckaa136e52012-12-04 03:26:05 -0800775 u16 have_temp;
776 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700777 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800778#ifdef CONFIG_PM
779 /* Remember extra register values over suspend/resume */
780 u8 vbat;
781 u8 fandiv1;
782 u8 fandiv2;
783#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700784};
785
786struct nct6775_sio_data {
787 int sioreg;
788 enum kinds kind;
789};
790
Guenter Roeckf73cf632013-03-18 09:22:50 -0700791struct sensor_device_template {
792 struct device_attribute dev_attr;
793 union {
794 struct {
795 u8 nr;
796 u8 index;
797 } s;
798 int index;
799 } u;
800 bool s2; /* true if both index and nr are used */
801};
802
803struct sensor_device_attr_u {
804 union {
805 struct sensor_device_attribute a1;
806 struct sensor_device_attribute_2 a2;
807 } u;
808 char name[32];
809};
810
811#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
812 .attr = {.name = _template, .mode = _mode }, \
813 .show = _show, \
814 .store = _store, \
815}
816
817#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
818 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
819 .u.index = _index, \
820 .s2 = false }
821
822#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
823 _nr, _index) \
824 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
825 .u.s.index = _index, \
826 .u.s.nr = _nr, \
827 .s2 = true }
828
829#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
830static struct sensor_device_template sensor_dev_template_##_name \
831 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
832 _index)
833
834#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
835 _nr, _index) \
836static struct sensor_device_template sensor_dev_template_##_name \
837 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
838 _nr, _index)
839
840struct sensor_template_group {
841 struct sensor_device_template **templates;
842 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
843 int base;
844};
845
846static struct attribute_group *
847nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
848 int repeat)
849{
850 struct attribute_group *group;
851 struct sensor_device_attr_u *su;
852 struct sensor_device_attribute *a;
853 struct sensor_device_attribute_2 *a2;
854 struct attribute **attrs;
855 struct sensor_device_template **t;
856 int err, i, j, count;
857
858 if (repeat <= 0)
859 return ERR_PTR(-EINVAL);
860
861 t = tg->templates;
862 for (count = 0; *t; t++, count++)
863 ;
864
865 if (count == 0)
866 return ERR_PTR(-EINVAL);
867
868 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
869 if (group == NULL)
870 return ERR_PTR(-ENOMEM);
871
872 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
873 GFP_KERNEL);
874 if (attrs == NULL)
875 return ERR_PTR(-ENOMEM);
876
877 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
878 GFP_KERNEL);
879 if (su == NULL)
880 return ERR_PTR(-ENOMEM);
881
882 group->attrs = attrs;
883 group->is_visible = tg->is_visible;
884
885 for (i = 0; i < repeat; i++) {
886 t = tg->templates;
887 for (j = 0; *t != NULL; j++) {
888 snprintf(su->name, sizeof(su->name),
889 (*t)->dev_attr.attr.name, tg->base + i);
890 if ((*t)->s2) {
891 a2 = &su->u.a2;
892 a2->dev_attr.attr.name = su->name;
893 a2->nr = (*t)->u.s.nr + i;
894 a2->index = (*t)->u.s.index;
895 a2->dev_attr.attr.mode =
896 (*t)->dev_attr.attr.mode;
897 a2->dev_attr.show = (*t)->dev_attr.show;
898 a2->dev_attr.store = (*t)->dev_attr.store;
899 *attrs = &a2->dev_attr.attr;
900 } else {
901 a = &su->u.a1;
902 a->dev_attr.attr.name = su->name;
903 a->index = (*t)->u.index + i;
904 a->dev_attr.attr.mode =
905 (*t)->dev_attr.attr.mode;
906 a->dev_attr.show = (*t)->dev_attr.show;
907 a->dev_attr.store = (*t)->dev_attr.store;
908 *attrs = &a->dev_attr.attr;
909 }
910 attrs++;
911 su++;
912 t++;
913 }
914 }
915
916 err = sysfs_create_group(&dev->kobj, group);
917 if (err)
918 return ERR_PTR(-ENOMEM);
919
920 return group;
921}
922
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700923static bool is_word_sized(struct nct6775_data *data, u16 reg)
924{
925 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -0700926 case nct6106:
927 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
928 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
929 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700930 case nct6775:
931 return (((reg & 0xff00) == 0x100 ||
932 (reg & 0xff00) == 0x200) &&
933 ((reg & 0x00ff) == 0x50 ||
934 (reg & 0x00ff) == 0x53 ||
935 (reg & 0x00ff) == 0x55)) ||
936 (reg & 0xfff0) == 0x630 ||
937 reg == 0x640 || reg == 0x642 ||
938 reg == 0x662 ||
939 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
940 reg == 0x73 || reg == 0x75 || reg == 0x77;
941 case nct6776:
942 return (((reg & 0xff00) == 0x100 ||
943 (reg & 0xff00) == 0x200) &&
944 ((reg & 0x00ff) == 0x50 ||
945 (reg & 0x00ff) == 0x53 ||
946 (reg & 0x00ff) == 0x55)) ||
947 (reg & 0xfff0) == 0x630 ||
948 reg == 0x402 ||
949 reg == 0x640 || reg == 0x642 ||
950 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
951 reg == 0x73 || reg == 0x75 || reg == 0x77;
952 case nct6779:
953 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
954 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
955 reg == 0x402 ||
956 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
957 reg == 0x640 || reg == 0x642 ||
958 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
959 reg == 0x7b;
960 }
961 return false;
962}
963
964/*
965 * On older chips, only registers 0x50-0x5f are banked.
966 * On more recent chips, all registers are banked.
967 * Assume that is the case and set the bank number for each access.
968 * Cache the bank number so it only needs to be set if it changes.
969 */
970static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
971{
972 u8 bank = reg >> 8;
973 if (data->bank != bank) {
974 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
975 outb_p(bank, data->addr + DATA_REG_OFFSET);
976 data->bank = bank;
977 }
978}
979
980static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
981{
982 int res, word_sized = is_word_sized(data, reg);
983
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700984 nct6775_set_bank(data, reg);
985 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
986 res = inb_p(data->addr + DATA_REG_OFFSET);
987 if (word_sized) {
988 outb_p((reg & 0xff) + 1,
989 data->addr + ADDR_REG_OFFSET);
990 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
991 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700992 return res;
993}
994
995static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
996{
997 int word_sized = is_word_sized(data, reg);
998
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700999 nct6775_set_bank(data, reg);
1000 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1001 if (word_sized) {
1002 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1003 outb_p((reg & 0xff) + 1,
1004 data->addr + ADDR_REG_OFFSET);
1005 }
1006 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001007 return 0;
1008}
1009
Guenter Roeckaa136e52012-12-04 03:26:05 -08001010/* We left-align 8-bit temperature values to make the code simpler */
1011static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1012{
1013 u16 res;
1014
1015 res = nct6775_read_value(data, reg);
1016 if (!is_word_sized(data, reg))
1017 res <<= 8;
1018
1019 return res;
1020}
1021
1022static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1023{
1024 if (!is_word_sized(data, reg))
1025 value >>= 8;
1026 return nct6775_write_value(data, reg, value);
1027}
1028
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001029/* This function assumes that the caller holds data->update_lock */
1030static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1031{
1032 u8 reg;
1033
1034 switch (nr) {
1035 case 0:
1036 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1037 | (data->fan_div[0] & 0x7);
1038 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1039 break;
1040 case 1:
1041 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1042 | ((data->fan_div[1] << 4) & 0x70);
1043 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1044 break;
1045 case 2:
1046 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1047 | (data->fan_div[2] & 0x7);
1048 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1049 break;
1050 case 3:
1051 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1052 | ((data->fan_div[3] << 4) & 0x70);
1053 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1054 break;
1055 }
1056}
1057
1058static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1059{
1060 if (data->kind == nct6775)
1061 nct6775_write_fan_div(data, nr);
1062}
1063
1064static void nct6775_update_fan_div(struct nct6775_data *data)
1065{
1066 u8 i;
1067
1068 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1069 data->fan_div[0] = i & 0x7;
1070 data->fan_div[1] = (i & 0x70) >> 4;
1071 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1072 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001073 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001074 data->fan_div[3] = (i & 0x70) >> 4;
1075}
1076
1077static void nct6775_update_fan_div_common(struct nct6775_data *data)
1078{
1079 if (data->kind == nct6775)
1080 nct6775_update_fan_div(data);
1081}
1082
1083static void nct6775_init_fan_div(struct nct6775_data *data)
1084{
1085 int i;
1086
1087 nct6775_update_fan_div_common(data);
1088 /*
1089 * For all fans, start with highest divider value if the divider
1090 * register is not initialized. This ensures that we get a
1091 * reading from the fan count register, even if it is not optimal.
1092 * We'll compute a better divider later on.
1093 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001094 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001095 if (!(data->has_fan & (1 << i)))
1096 continue;
1097 if (data->fan_div[i] == 0) {
1098 data->fan_div[i] = 7;
1099 nct6775_write_fan_div_common(data, i);
1100 }
1101 }
1102}
1103
1104static void nct6775_init_fan_common(struct device *dev,
1105 struct nct6775_data *data)
1106{
1107 int i;
1108 u8 reg;
1109
1110 if (data->has_fan_div)
1111 nct6775_init_fan_div(data);
1112
1113 /*
1114 * If fan_min is not set (0), set it to 0xff to disable it. This
1115 * prevents the unnecessary warning when fanX_min is reported as 0.
1116 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001117 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001118 if (data->has_fan_min & (1 << i)) {
1119 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1120 if (!reg)
1121 nct6775_write_value(data, data->REG_FAN_MIN[i],
1122 data->has_fan_div ? 0xff
1123 : 0xff1f);
1124 }
1125 }
1126}
1127
1128static void nct6775_select_fan_div(struct device *dev,
1129 struct nct6775_data *data, int nr, u16 reg)
1130{
1131 u8 fan_div = data->fan_div[nr];
1132 u16 fan_min;
1133
1134 if (!data->has_fan_div)
1135 return;
1136
1137 /*
1138 * If we failed to measure the fan speed, or the reported value is not
1139 * in the optimal range, and the clock divider can be modified,
1140 * let's try that for next time.
1141 */
1142 if (reg == 0x00 && fan_div < 0x07)
1143 fan_div++;
1144 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1145 fan_div--;
1146
1147 if (fan_div != data->fan_div[nr]) {
1148 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1149 nr + 1, div_from_reg(data->fan_div[nr]),
1150 div_from_reg(fan_div));
1151
1152 /* Preserve min limit if possible */
1153 if (data->has_fan_min & (1 << nr)) {
1154 fan_min = data->fan_min[nr];
1155 if (fan_div > data->fan_div[nr]) {
1156 if (fan_min != 255 && fan_min > 1)
1157 fan_min >>= 1;
1158 } else {
1159 if (fan_min != 255) {
1160 fan_min <<= 1;
1161 if (fan_min > 254)
1162 fan_min = 254;
1163 }
1164 }
1165 if (fan_min != data->fan_min[nr]) {
1166 data->fan_min[nr] = fan_min;
1167 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1168 fan_min);
1169 }
1170 }
1171 data->fan_div[nr] = fan_div;
1172 nct6775_write_fan_div_common(data, nr);
1173 }
1174}
1175
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001176static void nct6775_update_pwm(struct device *dev)
1177{
1178 struct nct6775_data *data = dev_get_drvdata(dev);
1179 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001180 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001181 bool duty_is_dc;
1182
1183 for (i = 0; i < data->pwm_num; i++) {
1184 if (!(data->has_pwm & (1 << i)))
1185 continue;
1186
1187 duty_is_dc = data->REG_PWM_MODE[i] &&
1188 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1189 & data->PWM_MODE_MASK[i]);
1190 data->pwm_mode[i] = duty_is_dc;
1191
1192 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1193 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1194 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1195 data->pwm[j][i]
1196 = nct6775_read_value(data,
1197 data->REG_PWM[j][i]);
1198 }
1199 }
1200
1201 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1202 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001203
1204 if (!data->temp_tolerance[0][i] ||
1205 data->pwm_enable[i] != speed_cruise)
1206 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1207 if (!data->target_speed_tolerance[i] ||
1208 data->pwm_enable[i] == speed_cruise) {
1209 u8 t = fanmodecfg & 0x0f;
1210 if (data->REG_TOLERANCE_H) {
1211 t |= (nct6775_read_value(data,
1212 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1213 }
1214 data->target_speed_tolerance[i] = t;
1215 }
1216
1217 data->temp_tolerance[1][i] =
1218 nct6775_read_value(data,
1219 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1220
1221 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1222 data->pwm_temp_sel[i] = reg & 0x1f;
1223 /* If fan can stop, report floor as 0 */
1224 if (reg & 0x80)
1225 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001226
1227 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1228 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1229 /* If weight is disabled, report weight source as 0 */
1230 if (j == 1 && !(reg & 0x80))
1231 data->pwm_weight_temp_sel[i] = 0;
1232
1233 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001234 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001235 data->weight_temp[j][i]
1236 = nct6775_read_value(data,
1237 data->REG_WEIGHT_TEMP[j][i]);
1238 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001239 }
1240}
1241
1242static void nct6775_update_pwm_limits(struct device *dev)
1243{
1244 struct nct6775_data *data = dev_get_drvdata(dev);
1245 int i, j;
1246 u8 reg;
1247 u16 reg_t;
1248
1249 for (i = 0; i < data->pwm_num; i++) {
1250 if (!(data->has_pwm & (1 << i)))
1251 continue;
1252
Guenter Roeckc409fd42013-04-09 05:04:00 -07001253 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001254 data->fan_time[j][i] =
1255 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1256 }
1257
1258 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1259 /* Update only in matching mode or if never updated */
1260 if (!data->target_temp[i] ||
1261 data->pwm_enable[i] == thermal_cruise)
1262 data->target_temp[i] = reg_t & data->target_temp_mask;
1263 if (!data->target_speed[i] ||
1264 data->pwm_enable[i] == speed_cruise) {
1265 if (data->REG_TOLERANCE_H) {
1266 reg_t |= (nct6775_read_value(data,
1267 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1268 }
1269 data->target_speed[i] = reg_t;
1270 }
1271
1272 for (j = 0; j < data->auto_pwm_num; j++) {
1273 data->auto_pwm[i][j] =
1274 nct6775_read_value(data,
1275 NCT6775_AUTO_PWM(data, i, j));
1276 data->auto_temp[i][j] =
1277 nct6775_read_value(data,
1278 NCT6775_AUTO_TEMP(data, i, j));
1279 }
1280
1281 /* critical auto_pwm temperature data */
1282 data->auto_temp[i][data->auto_pwm_num] =
1283 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1284
1285 switch (data->kind) {
1286 case nct6775:
1287 reg = nct6775_read_value(data,
1288 NCT6775_REG_CRITICAL_ENAB[i]);
1289 data->auto_pwm[i][data->auto_pwm_num] =
1290 (reg & 0x02) ? 0xff : 0x00;
1291 break;
1292 case nct6776:
1293 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1294 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001295 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001296 case nct6779:
1297 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001298 data->REG_CRITICAL_PWM_ENABLE[i]);
1299 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1300 reg = nct6775_read_value(data,
1301 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001302 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001303 reg = 0xff;
1304 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001305 break;
1306 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001307 }
1308}
1309
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001310static struct nct6775_data *nct6775_update_device(struct device *dev)
1311{
1312 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001313 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001314
1315 mutex_lock(&data->update_lock);
1316
Guenter Roeck6445e662013-04-21 09:13:28 -07001317 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001318 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001319 /* Fan clock dividers */
1320 nct6775_update_fan_div_common(data);
1321
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001322 /* Measured voltages and limits */
1323 for (i = 0; i < data->in_num; i++) {
1324 if (!(data->have_in & (1 << i)))
1325 continue;
1326
1327 data->in[i][0] = nct6775_read_value(data,
1328 data->REG_VIN[i]);
1329 data->in[i][1] = nct6775_read_value(data,
1330 data->REG_IN_MINMAX[0][i]);
1331 data->in[i][2] = nct6775_read_value(data,
1332 data->REG_IN_MINMAX[1][i]);
1333 }
1334
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001335 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001336 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001337 u16 reg;
1338
1339 if (!(data->has_fan & (1 << i)))
1340 continue;
1341
1342 reg = nct6775_read_value(data, data->REG_FAN[i]);
1343 data->rpm[i] = data->fan_from_reg(reg,
1344 data->fan_div[i]);
1345
1346 if (data->has_fan_min & (1 << i))
1347 data->fan_min[i] = nct6775_read_value(data,
1348 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001349 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001350 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1351 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001352
1353 nct6775_select_fan_div(dev, data, i, reg);
1354 }
1355
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001356 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001357 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001358
Guenter Roeckaa136e52012-12-04 03:26:05 -08001359 /* Measured temperatures and limits */
1360 for (i = 0; i < NUM_TEMP; i++) {
1361 if (!(data->have_temp & (1 << i)))
1362 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001363 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001364 if (data->reg_temp[j][i])
1365 data->temp[j][i]
1366 = nct6775_read_temp(data,
1367 data->reg_temp[j][i]);
1368 }
1369 if (!(data->have_temp_fixed & (1 << i)))
1370 continue;
1371 data->temp_offset[i]
1372 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1373 }
1374
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001375 data->alarms = 0;
1376 for (i = 0; i < NUM_REG_ALARM; i++) {
1377 u8 alarm;
1378 if (!data->REG_ALARM[i])
1379 continue;
1380 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1381 data->alarms |= ((u64)alarm) << (i << 3);
1382 }
1383
1384 data->last_updated = jiffies;
1385 data->valid = true;
1386 }
1387
1388 mutex_unlock(&data->update_lock);
1389 return data;
1390}
1391
1392/*
1393 * Sysfs callback functions
1394 */
1395static ssize_t
1396show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1397{
1398 struct nct6775_data *data = nct6775_update_device(dev);
1399 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1400 int nr = sattr->nr;
1401 int index = sattr->index;
1402 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1403}
1404
1405static ssize_t
1406store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1407 size_t count)
1408{
1409 struct nct6775_data *data = dev_get_drvdata(dev);
1410 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1411 int nr = sattr->nr;
1412 int index = sattr->index;
1413 unsigned long val;
1414 int err = kstrtoul(buf, 10, &val);
1415 if (err < 0)
1416 return err;
1417 mutex_lock(&data->update_lock);
1418 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001419 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001420 data->in[nr][index]);
1421 mutex_unlock(&data->update_lock);
1422 return count;
1423}
1424
1425static ssize_t
1426show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1427{
1428 struct nct6775_data *data = nct6775_update_device(dev);
1429 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1430 int nr = data->ALARM_BITS[sattr->index];
1431 return sprintf(buf, "%u\n",
1432 (unsigned int)((data->alarms >> nr) & 0x01));
1433}
1434
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001435static int find_temp_source(struct nct6775_data *data, int index, int count)
1436{
1437 int source = data->temp_src[index];
1438 int nr;
1439
1440 for (nr = 0; nr < count; nr++) {
1441 int src;
1442
1443 src = nct6775_read_value(data,
1444 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1445 if (src == source)
1446 return nr;
1447 }
1448 return -1;
1449}
1450
1451static ssize_t
1452show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1453{
1454 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1455 struct nct6775_data *data = nct6775_update_device(dev);
1456 unsigned int alarm = 0;
1457 int nr;
1458
1459 /*
1460 * For temperatures, there is no fixed mapping from registers to alarm
1461 * bits. Alarm bits are determined by the temperature source mapping.
1462 */
1463 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1464 if (nr >= 0) {
1465 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1466 alarm = (data->alarms >> bit) & 0x01;
1467 }
1468 return sprintf(buf, "%u\n", alarm);
1469}
1470
Guenter Roeckf73cf632013-03-18 09:22:50 -07001471static umode_t nct6775_in_is_visible(struct kobject *kobj,
1472 struct attribute *attr, int index)
1473{
1474 struct device *dev = container_of(kobj, struct device, kobj);
1475 struct nct6775_data *data = dev_get_drvdata(dev);
1476 int in = index / 4; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001477
Guenter Roeckf73cf632013-03-18 09:22:50 -07001478 if (!(data->have_in & (1 << in)))
1479 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001480
Guenter Roeckf73cf632013-03-18 09:22:50 -07001481 return attr->mode;
1482}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001483
Guenter Roeckf73cf632013-03-18 09:22:50 -07001484SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1485SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
1486SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1487 store_in_reg, 0, 1);
1488SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1489 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001490
Guenter Roeckf73cf632013-03-18 09:22:50 -07001491/*
1492 * nct6775_in_is_visible uses the index into the following array
1493 * to determine if attributes should be created or not.
1494 * Any change in order or content must be matched.
1495 */
1496static struct sensor_device_template *nct6775_attributes_in_template[] = {
1497 &sensor_dev_template_in_input,
1498 &sensor_dev_template_in_alarm,
1499 &sensor_dev_template_in_min,
1500 &sensor_dev_template_in_max,
1501 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001502};
1503
Guenter Roeckf73cf632013-03-18 09:22:50 -07001504static struct sensor_template_group nct6775_in_template_group = {
1505 .templates = nct6775_attributes_in_template,
1506 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001507};
1508
1509static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001510show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1511{
1512 struct nct6775_data *data = nct6775_update_device(dev);
1513 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1514 int nr = sattr->index;
1515 return sprintf(buf, "%d\n", data->rpm[nr]);
1516}
1517
1518static ssize_t
1519show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1520{
1521 struct nct6775_data *data = nct6775_update_device(dev);
1522 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1523 int nr = sattr->index;
1524 return sprintf(buf, "%d\n",
1525 data->fan_from_reg_min(data->fan_min[nr],
1526 data->fan_div[nr]));
1527}
1528
1529static ssize_t
1530show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1531{
1532 struct nct6775_data *data = nct6775_update_device(dev);
1533 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1534 int nr = sattr->index;
1535 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1536}
1537
1538static ssize_t
1539store_fan_min(struct device *dev, struct device_attribute *attr,
1540 const char *buf, size_t count)
1541{
1542 struct nct6775_data *data = dev_get_drvdata(dev);
1543 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1544 int nr = sattr->index;
1545 unsigned long val;
1546 int err;
1547 unsigned int reg;
1548 u8 new_div;
1549
1550 err = kstrtoul(buf, 10, &val);
1551 if (err < 0)
1552 return err;
1553
1554 mutex_lock(&data->update_lock);
1555 if (!data->has_fan_div) {
1556 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1557 if (!val) {
1558 val = 0xff1f;
1559 } else {
1560 if (val > 1350000U)
1561 val = 135000U;
1562 val = 1350000U / val;
1563 val = (val & 0x1f) | ((val << 3) & 0xff00);
1564 }
1565 data->fan_min[nr] = val;
1566 goto write_min; /* Leave fan divider alone */
1567 }
1568 if (!val) {
1569 /* No min limit, alarm disabled */
1570 data->fan_min[nr] = 255;
1571 new_div = data->fan_div[nr]; /* No change */
1572 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1573 goto write_div;
1574 }
1575 reg = 1350000U / val;
1576 if (reg >= 128 * 255) {
1577 /*
1578 * Speed below this value cannot possibly be represented,
1579 * even with the highest divider (128)
1580 */
1581 data->fan_min[nr] = 254;
1582 new_div = 7; /* 128 == (1 << 7) */
1583 dev_warn(dev,
1584 "fan%u low limit %lu below minimum %u, set to minimum\n",
1585 nr + 1, val, data->fan_from_reg_min(254, 7));
1586 } else if (!reg) {
1587 /*
1588 * Speed above this value cannot possibly be represented,
1589 * even with the lowest divider (1)
1590 */
1591 data->fan_min[nr] = 1;
1592 new_div = 0; /* 1 == (1 << 0) */
1593 dev_warn(dev,
1594 "fan%u low limit %lu above maximum %u, set to maximum\n",
1595 nr + 1, val, data->fan_from_reg_min(1, 0));
1596 } else {
1597 /*
1598 * Automatically pick the best divider, i.e. the one such
1599 * that the min limit will correspond to a register value
1600 * in the 96..192 range
1601 */
1602 new_div = 0;
1603 while (reg > 192 && new_div < 7) {
1604 reg >>= 1;
1605 new_div++;
1606 }
1607 data->fan_min[nr] = reg;
1608 }
1609
1610write_div:
1611 /*
1612 * Write both the fan clock divider (if it changed) and the new
1613 * fan min (unconditionally)
1614 */
1615 if (new_div != data->fan_div[nr]) {
1616 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1617 nr + 1, div_from_reg(data->fan_div[nr]),
1618 div_from_reg(new_div));
1619 data->fan_div[nr] = new_div;
1620 nct6775_write_fan_div_common(data, nr);
1621 /* Give the chip time to sample a new speed value */
1622 data->last_updated = jiffies;
1623 }
1624
1625write_min:
1626 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1627 mutex_unlock(&data->update_lock);
1628
1629 return count;
1630}
1631
Guenter Roeck5c25d952012-12-11 07:29:06 -08001632static ssize_t
1633show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1634{
1635 struct nct6775_data *data = nct6775_update_device(dev);
1636 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1637 int p = data->fan_pulses[sattr->index];
1638
1639 return sprintf(buf, "%d\n", p ? : 4);
1640}
1641
1642static ssize_t
1643store_fan_pulses(struct device *dev, struct device_attribute *attr,
1644 const char *buf, size_t count)
1645{
1646 struct nct6775_data *data = dev_get_drvdata(dev);
1647 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1648 int nr = sattr->index;
1649 unsigned long val;
1650 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001651 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001652
1653 err = kstrtoul(buf, 10, &val);
1654 if (err < 0)
1655 return err;
1656
1657 if (val > 4)
1658 return -EINVAL;
1659
1660 mutex_lock(&data->update_lock);
1661 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001662 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1663 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1664 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1665 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001666 mutex_unlock(&data->update_lock);
1667
1668 return count;
1669}
1670
Guenter Roeckf73cf632013-03-18 09:22:50 -07001671static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1672 struct attribute *attr, int index)
1673{
1674 struct device *dev = container_of(kobj, struct device, kobj);
1675 struct nct6775_data *data = dev_get_drvdata(dev);
1676 int fan = index / 5; /* fan index */
1677 int nr = index % 5; /* attribute index */
1678
1679 if (!(data->has_fan & (1 << fan)))
1680 return 0;
1681
1682 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1683 return 0;
1684 if (nr == 3 && !(data->has_fan_min & (1 << fan)))
1685 return 0;
1686 if (nr == 4 && data->kind != nct6775)
1687 return 0;
1688
1689 return attr->mode;
1690}
1691
1692SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1693SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1694 FAN_ALARM_BASE);
1695SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1696 store_fan_pulses, 0);
1697SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1698 store_fan_min, 0);
1699SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1700
1701/*
1702 * nct6775_fan_is_visible uses the index into the following array
1703 * to determine if attributes should be created or not.
1704 * Any change in order or content must be matched.
1705 */
1706static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1707 &sensor_dev_template_fan_input,
1708 &sensor_dev_template_fan_alarm, /* 1 */
1709 &sensor_dev_template_fan_pulses,
1710 &sensor_dev_template_fan_min, /* 3 */
1711 &sensor_dev_template_fan_div, /* 4 */
1712 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001713};
1714
Guenter Roeckf73cf632013-03-18 09:22:50 -07001715static struct sensor_template_group nct6775_fan_template_group = {
1716 .templates = nct6775_attributes_fan_template,
1717 .is_visible = nct6775_fan_is_visible,
1718 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001719};
1720
1721static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001722show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1723{
1724 struct nct6775_data *data = nct6775_update_device(dev);
1725 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1726 int nr = sattr->index;
1727 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1728}
1729
1730static ssize_t
1731show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1732{
1733 struct nct6775_data *data = nct6775_update_device(dev);
1734 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1735 int nr = sattr->nr;
1736 int index = sattr->index;
1737
1738 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1739}
1740
1741static ssize_t
1742store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1743 size_t count)
1744{
1745 struct nct6775_data *data = dev_get_drvdata(dev);
1746 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1747 int nr = sattr->nr;
1748 int index = sattr->index;
1749 int err;
1750 long val;
1751
1752 err = kstrtol(buf, 10, &val);
1753 if (err < 0)
1754 return err;
1755
1756 mutex_lock(&data->update_lock);
1757 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1758 nct6775_write_temp(data, data->reg_temp[index][nr],
1759 data->temp[index][nr]);
1760 mutex_unlock(&data->update_lock);
1761 return count;
1762}
1763
1764static ssize_t
1765show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1766{
1767 struct nct6775_data *data = nct6775_update_device(dev);
1768 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1769
1770 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1771}
1772
1773static ssize_t
1774store_temp_offset(struct device *dev, struct device_attribute *attr,
1775 const char *buf, size_t count)
1776{
1777 struct nct6775_data *data = dev_get_drvdata(dev);
1778 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1779 int nr = sattr->index;
1780 long val;
1781 int err;
1782
1783 err = kstrtol(buf, 10, &val);
1784 if (err < 0)
1785 return err;
1786
1787 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1788
1789 mutex_lock(&data->update_lock);
1790 data->temp_offset[nr] = val;
1791 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1792 mutex_unlock(&data->update_lock);
1793
1794 return count;
1795}
1796
1797static ssize_t
1798show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1799{
1800 struct nct6775_data *data = nct6775_update_device(dev);
1801 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1802 int nr = sattr->index;
1803 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
1804}
1805
1806static ssize_t
1807store_temp_type(struct device *dev, struct device_attribute *attr,
1808 const char *buf, size_t count)
1809{
1810 struct nct6775_data *data = nct6775_update_device(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 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001816
1817 err = kstrtoul(buf, 10, &val);
1818 if (err < 0)
1819 return err;
1820
1821 if (val != 1 && val != 3 && val != 4)
1822 return -EINVAL;
1823
1824 mutex_lock(&data->update_lock);
1825
1826 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07001827 vbit = 0x02 << nr;
1828 dbit = data->DIODE_MASK << nr;
1829 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
1830 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001831 switch (val) {
1832 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07001833 vbat |= vbit;
1834 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001835 break;
1836 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07001837 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001838 break;
1839 case 4: /* thermistor */
1840 break;
1841 }
1842 nct6775_write_value(data, data->REG_VBAT, vbat);
1843 nct6775_write_value(data, data->REG_DIODE, diode);
1844
1845 mutex_unlock(&data->update_lock);
1846 return count;
1847}
1848
Guenter Roeckf73cf632013-03-18 09:22:50 -07001849static umode_t nct6775_temp_is_visible(struct kobject *kobj,
1850 struct attribute *attr, int index)
1851{
1852 struct device *dev = container_of(kobj, struct device, kobj);
1853 struct nct6775_data *data = dev_get_drvdata(dev);
1854 int temp = index / 8; /* temp index */
1855 int nr = index % 8; /* attribute index */
1856
1857 if (!(data->have_temp & (1 << temp)))
1858 return 0;
1859
1860 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
1861 return 0; /* alarm */
1862
1863 if (nr == 3 && !data->reg_temp[1][temp]) /* max */
1864 return 0;
1865
1866 if (nr == 4 && !data->reg_temp[2][temp]) /* max_hyst */
1867 return 0;
1868
1869 if (nr == 5 && !data->reg_temp[3][temp]) /* crit */
1870 return 0;
1871
1872 if (nr > 5 && !(data->have_temp_fixed & (1 << temp)))
1873 return 0;
1874
1875 return attr->mode;
1876}
1877
1878SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
1879SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
1880SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
1881 store_temp, 0, 1);
1882SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
1883 show_temp, store_temp, 0, 2);
1884SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
1885 store_temp, 0, 3);
1886SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
1887 show_temp_offset, store_temp_offset, 0);
1888SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
1889 store_temp_type, 0);
1890SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
1891
1892/*
1893 * nct6775_temp_is_visible uses the index into the following array
1894 * to determine if attributes should be created or not.
1895 * Any change in order or content must be matched.
1896 */
1897static struct sensor_device_template *nct6775_attributes_temp_template[] = {
1898 &sensor_dev_template_temp_input,
1899 &sensor_dev_template_temp_label,
1900 &sensor_dev_template_temp_alarm, /* 2 */
1901 &sensor_dev_template_temp_max, /* 3 */
1902 &sensor_dev_template_temp_max_hyst, /* 4 */
1903 &sensor_dev_template_temp_crit, /* 5 */
1904 &sensor_dev_template_temp_offset, /* 6 */
1905 &sensor_dev_template_temp_type, /* 7 */
1906 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08001907};
1908
Guenter Roeckf73cf632013-03-18 09:22:50 -07001909static struct sensor_template_group nct6775_temp_template_group = {
1910 .templates = nct6775_attributes_temp_template,
1911 .is_visible = nct6775_temp_is_visible,
1912 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08001913};
1914
Guenter Roeckaa136e52012-12-04 03:26:05 -08001915static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001916show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
1917{
1918 struct nct6775_data *data = nct6775_update_device(dev);
1919 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1920
1921 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
1922}
1923
1924static ssize_t
1925store_pwm_mode(struct device *dev, struct device_attribute *attr,
1926 const char *buf, size_t count)
1927{
1928 struct nct6775_data *data = dev_get_drvdata(dev);
1929 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1930 int nr = sattr->index;
1931 unsigned long val;
1932 int err;
1933 u8 reg;
1934
1935 err = kstrtoul(buf, 10, &val);
1936 if (err < 0)
1937 return err;
1938
1939 if (val > 1)
1940 return -EINVAL;
1941
1942 /* Setting DC mode is not supported for all chips/channels */
1943 if (data->REG_PWM_MODE[nr] == 0) {
1944 if (val)
1945 return -EINVAL;
1946 return count;
1947 }
1948
1949 mutex_lock(&data->update_lock);
1950 data->pwm_mode[nr] = val;
1951 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
1952 reg &= ~data->PWM_MODE_MASK[nr];
1953 if (val)
1954 reg |= data->PWM_MODE_MASK[nr];
1955 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
1956 mutex_unlock(&data->update_lock);
1957 return count;
1958}
1959
1960static ssize_t
1961show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
1962{
1963 struct nct6775_data *data = nct6775_update_device(dev);
1964 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1965 int nr = sattr->nr;
1966 int index = sattr->index;
1967 int pwm;
1968
1969 /*
1970 * For automatic fan control modes, show current pwm readings.
1971 * Otherwise, show the configured value.
1972 */
1973 if (index == 0 && data->pwm_enable[nr] > manual)
1974 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
1975 else
1976 pwm = data->pwm[index][nr];
1977
1978 return sprintf(buf, "%d\n", pwm);
1979}
1980
1981static ssize_t
1982store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
1983 size_t count)
1984{
1985 struct nct6775_data *data = dev_get_drvdata(dev);
1986 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1987 int nr = sattr->nr;
1988 int index = sattr->index;
1989 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001990 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
1991 int maxval[7]
1992 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001993 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001994 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001995
1996 err = kstrtoul(buf, 10, &val);
1997 if (err < 0)
1998 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001999 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002000
2001 mutex_lock(&data->update_lock);
2002 data->pwm[index][nr] = val;
2003 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002004 if (index == 2) { /* floor: disable if val == 0 */
2005 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2006 reg &= 0x7f;
2007 if (val)
2008 reg |= 0x80;
2009 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2010 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002011 mutex_unlock(&data->update_lock);
2012 return count;
2013}
2014
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002015/* Returns 0 if OK, -EINVAL otherwise */
2016static int check_trip_points(struct nct6775_data *data, int nr)
2017{
2018 int i;
2019
2020 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2021 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2022 return -EINVAL;
2023 }
2024 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2025 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2026 return -EINVAL;
2027 }
2028 /* validate critical temperature and pwm if enabled (pwm > 0) */
2029 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2030 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2031 data->auto_temp[nr][data->auto_pwm_num] ||
2032 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2033 data->auto_pwm[nr][data->auto_pwm_num])
2034 return -EINVAL;
2035 }
2036 return 0;
2037}
2038
2039static void pwm_update_registers(struct nct6775_data *data, int nr)
2040{
2041 u8 reg;
2042
2043 switch (data->pwm_enable[nr]) {
2044 case off:
2045 case manual:
2046 break;
2047 case speed_cruise:
2048 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2049 reg = (reg & ~data->tolerance_mask) |
2050 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2051 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2052 nct6775_write_value(data, data->REG_TARGET[nr],
2053 data->target_speed[nr] & 0xff);
2054 if (data->REG_TOLERANCE_H) {
2055 reg = (data->target_speed[nr] >> 8) & 0x0f;
2056 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2057 nct6775_write_value(data,
2058 data->REG_TOLERANCE_H[nr],
2059 reg);
2060 }
2061 break;
2062 case thermal_cruise:
2063 nct6775_write_value(data, data->REG_TARGET[nr],
2064 data->target_temp[nr]);
2065 /* intentional */
2066 default:
2067 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2068 reg = (reg & ~data->tolerance_mask) |
2069 data->temp_tolerance[0][nr];
2070 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2071 break;
2072 }
2073}
2074
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002075static ssize_t
2076show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2077{
2078 struct nct6775_data *data = nct6775_update_device(dev);
2079 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2080
2081 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2082}
2083
2084static ssize_t
2085store_pwm_enable(struct device *dev, struct device_attribute *attr,
2086 const char *buf, size_t count)
2087{
2088 struct nct6775_data *data = dev_get_drvdata(dev);
2089 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2090 int nr = sattr->index;
2091 unsigned long val;
2092 int err;
2093 u16 reg;
2094
2095 err = kstrtoul(buf, 10, &val);
2096 if (err < 0)
2097 return err;
2098
2099 if (val > sf4)
2100 return -EINVAL;
2101
2102 if (val == sf3 && data->kind != nct6775)
2103 return -EINVAL;
2104
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002105 if (val == sf4 && check_trip_points(data, nr)) {
2106 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2107 dev_err(dev, "Adjust trip points and try again\n");
2108 return -EINVAL;
2109 }
2110
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002111 mutex_lock(&data->update_lock);
2112 data->pwm_enable[nr] = val;
2113 if (val == off) {
2114 /*
2115 * turn off pwm control: select manual mode, set pwm to maximum
2116 */
2117 data->pwm[0][nr] = 255;
2118 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2119 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002120 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002121 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2122 reg &= 0x0f;
2123 reg |= pwm_enable_to_reg(val) << 4;
2124 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2125 mutex_unlock(&data->update_lock);
2126 return count;
2127}
2128
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002129static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002130show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002131{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002132 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002133
2134 for (i = 0; i < NUM_TEMP; i++) {
2135 if (!(data->have_temp & (1 << i)))
2136 continue;
2137 if (src == data->temp_src[i]) {
2138 sel = i + 1;
2139 break;
2140 }
2141 }
2142
2143 return sprintf(buf, "%d\n", sel);
2144}
2145
2146static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002147show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2148{
2149 struct nct6775_data *data = nct6775_update_device(dev);
2150 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2151 int index = sattr->index;
2152
2153 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2154}
2155
2156static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002157store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2158 const char *buf, size_t count)
2159{
2160 struct nct6775_data *data = nct6775_update_device(dev);
2161 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2162 int nr = sattr->index;
2163 unsigned long val;
2164 int err, reg, src;
2165
2166 err = kstrtoul(buf, 10, &val);
2167 if (err < 0)
2168 return err;
2169 if (val == 0 || val > NUM_TEMP)
2170 return -EINVAL;
2171 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2172 return -EINVAL;
2173
2174 mutex_lock(&data->update_lock);
2175 src = data->temp_src[val - 1];
2176 data->pwm_temp_sel[nr] = src;
2177 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2178 reg &= 0xe0;
2179 reg |= src;
2180 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2181 mutex_unlock(&data->update_lock);
2182
2183 return count;
2184}
2185
2186static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002187show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2188 char *buf)
2189{
2190 struct nct6775_data *data = nct6775_update_device(dev);
2191 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2192 int index = sattr->index;
2193
2194 return show_pwm_temp_sel_common(data, buf,
2195 data->pwm_weight_temp_sel[index]);
2196}
2197
2198static ssize_t
2199store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2200 const char *buf, size_t count)
2201{
2202 struct nct6775_data *data = nct6775_update_device(dev);
2203 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2204 int nr = sattr->index;
2205 unsigned long val;
2206 int err, reg, src;
2207
2208 err = kstrtoul(buf, 10, &val);
2209 if (err < 0)
2210 return err;
2211 if (val > NUM_TEMP)
2212 return -EINVAL;
2213 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2214 !data->temp_src[val - 1]))
2215 return -EINVAL;
2216
2217 mutex_lock(&data->update_lock);
2218 if (val) {
2219 src = data->temp_src[val - 1];
2220 data->pwm_weight_temp_sel[nr] = src;
2221 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2222 reg &= 0xe0;
2223 reg |= (src | 0x80);
2224 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2225 } else {
2226 data->pwm_weight_temp_sel[nr] = 0;
2227 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2228 reg &= 0x7f;
2229 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2230 }
2231 mutex_unlock(&data->update_lock);
2232
2233 return count;
2234}
2235
2236static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002237show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2238{
2239 struct nct6775_data *data = nct6775_update_device(dev);
2240 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2241
2242 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2243}
2244
2245static ssize_t
2246store_target_temp(struct device *dev, struct device_attribute *attr,
2247 const char *buf, size_t count)
2248{
2249 struct nct6775_data *data = dev_get_drvdata(dev);
2250 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2251 int nr = sattr->index;
2252 unsigned long val;
2253 int err;
2254
2255 err = kstrtoul(buf, 10, &val);
2256 if (err < 0)
2257 return err;
2258
2259 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2260 data->target_temp_mask);
2261
2262 mutex_lock(&data->update_lock);
2263 data->target_temp[nr] = val;
2264 pwm_update_registers(data, nr);
2265 mutex_unlock(&data->update_lock);
2266 return count;
2267}
2268
2269static ssize_t
2270show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2271{
2272 struct nct6775_data *data = nct6775_update_device(dev);
2273 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2274 int nr = sattr->index;
2275
2276 return sprintf(buf, "%d\n",
2277 fan_from_reg16(data->target_speed[nr],
2278 data->fan_div[nr]));
2279}
2280
2281static ssize_t
2282store_target_speed(struct device *dev, struct device_attribute *attr,
2283 const char *buf, size_t count)
2284{
2285 struct nct6775_data *data = dev_get_drvdata(dev);
2286 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2287 int nr = sattr->index;
2288 unsigned long val;
2289 int err;
2290 u16 speed;
2291
2292 err = kstrtoul(buf, 10, &val);
2293 if (err < 0)
2294 return err;
2295
2296 val = clamp_val(val, 0, 1350000U);
2297 speed = fan_to_reg(val, data->fan_div[nr]);
2298
2299 mutex_lock(&data->update_lock);
2300 data->target_speed[nr] = speed;
2301 pwm_update_registers(data, nr);
2302 mutex_unlock(&data->update_lock);
2303 return count;
2304}
2305
2306static ssize_t
2307show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2308 char *buf)
2309{
2310 struct nct6775_data *data = nct6775_update_device(dev);
2311 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2312 int nr = sattr->nr;
2313 int index = sattr->index;
2314
2315 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2316}
2317
2318static ssize_t
2319store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2320 const char *buf, size_t count)
2321{
2322 struct nct6775_data *data = dev_get_drvdata(dev);
2323 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2324 int nr = sattr->nr;
2325 int index = sattr->index;
2326 unsigned long val;
2327 int err;
2328
2329 err = kstrtoul(buf, 10, &val);
2330 if (err < 0)
2331 return err;
2332
2333 /* Limit tolerance as needed */
2334 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2335
2336 mutex_lock(&data->update_lock);
2337 data->temp_tolerance[index][nr] = val;
2338 if (index)
2339 pwm_update_registers(data, nr);
2340 else
2341 nct6775_write_value(data,
2342 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2343 val);
2344 mutex_unlock(&data->update_lock);
2345 return count;
2346}
2347
2348/*
2349 * Fan speed tolerance is a tricky beast, since the associated register is
2350 * a tick counter, but the value is reported and configured as rpm.
2351 * Compute resulting low and high rpm values and report the difference.
2352 */
2353static ssize_t
2354show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2355 char *buf)
2356{
2357 struct nct6775_data *data = nct6775_update_device(dev);
2358 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2359 int nr = sattr->index;
2360 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2361 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2362 int tolerance;
2363
2364 if (low <= 0)
2365 low = 1;
2366 if (high > 0xffff)
2367 high = 0xffff;
2368 if (high < low)
2369 high = low;
2370
2371 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2372 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2373
2374 return sprintf(buf, "%d\n", tolerance);
2375}
2376
2377static ssize_t
2378store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2379 const char *buf, size_t count)
2380{
2381 struct nct6775_data *data = dev_get_drvdata(dev);
2382 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2383 int nr = sattr->index;
2384 unsigned long val;
2385 int err;
2386 int low, high;
2387
2388 err = kstrtoul(buf, 10, &val);
2389 if (err < 0)
2390 return err;
2391
2392 high = fan_from_reg16(data->target_speed[nr],
2393 data->fan_div[nr]) + val;
2394 low = fan_from_reg16(data->target_speed[nr],
2395 data->fan_div[nr]) - val;
2396 if (low <= 0)
2397 low = 1;
2398 if (high < low)
2399 high = low;
2400
2401 val = (fan_to_reg(low, data->fan_div[nr]) -
2402 fan_to_reg(high, data->fan_div[nr])) / 2;
2403
2404 /* Limit tolerance as needed */
2405 val = clamp_val(val, 0, data->speed_tolerance_limit);
2406
2407 mutex_lock(&data->update_lock);
2408 data->target_speed_tolerance[nr] = val;
2409 pwm_update_registers(data, nr);
2410 mutex_unlock(&data->update_lock);
2411 return count;
2412}
2413
Guenter Roeckf73cf632013-03-18 09:22:50 -07002414SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2415SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2416 store_pwm_mode, 0);
2417SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2418 store_pwm_enable, 0);
2419SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2420 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2421SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2422 show_target_temp, store_target_temp, 0);
2423SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2424 show_target_speed, store_target_speed, 0);
2425SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2426 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002427
2428/* Smart Fan registers */
2429
2430static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002431show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2432{
2433 struct nct6775_data *data = nct6775_update_device(dev);
2434 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2435 int nr = sattr->nr;
2436 int index = sattr->index;
2437
2438 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2439}
2440
2441static ssize_t
2442store_weight_temp(struct device *dev, struct device_attribute *attr,
2443 const char *buf, size_t count)
2444{
2445 struct nct6775_data *data = dev_get_drvdata(dev);
2446 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2447 int nr = sattr->nr;
2448 int index = sattr->index;
2449 unsigned long val;
2450 int err;
2451
2452 err = kstrtoul(buf, 10, &val);
2453 if (err < 0)
2454 return err;
2455
2456 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2457
2458 mutex_lock(&data->update_lock);
2459 data->weight_temp[index][nr] = val;
2460 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2461 mutex_unlock(&data->update_lock);
2462 return count;
2463}
2464
Guenter Roeckf73cf632013-03-18 09:22:50 -07002465SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2466 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2467SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2468 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2469SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2470 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2471SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2472 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2473SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2474 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2475SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2476 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002477
2478static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002479show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2480{
2481 struct nct6775_data *data = nct6775_update_device(dev);
2482 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2483 int nr = sattr->nr;
2484 int index = sattr->index;
2485
2486 return sprintf(buf, "%d\n",
2487 step_time_from_reg(data->fan_time[index][nr],
2488 data->pwm_mode[nr]));
2489}
2490
2491static ssize_t
2492store_fan_time(struct device *dev, struct device_attribute *attr,
2493 const char *buf, size_t count)
2494{
2495 struct nct6775_data *data = dev_get_drvdata(dev);
2496 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2497 int nr = sattr->nr;
2498 int index = sattr->index;
2499 unsigned long val;
2500 int err;
2501
2502 err = kstrtoul(buf, 10, &val);
2503 if (err < 0)
2504 return err;
2505
2506 val = step_time_to_reg(val, data->pwm_mode[nr]);
2507 mutex_lock(&data->update_lock);
2508 data->fan_time[index][nr] = val;
2509 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2510 mutex_unlock(&data->update_lock);
2511 return count;
2512}
2513
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002514static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002515show_name(struct device *dev, struct device_attribute *attr, char *buf)
2516{
2517 struct nct6775_data *data = dev_get_drvdata(dev);
2518
2519 return sprintf(buf, "%s\n", data->name);
2520}
2521
2522static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2523
2524static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002525show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2526{
2527 struct nct6775_data *data = nct6775_update_device(dev);
2528 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2529
2530 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2531}
2532
2533static ssize_t
2534store_auto_pwm(struct device *dev, struct device_attribute *attr,
2535 const char *buf, size_t count)
2536{
2537 struct nct6775_data *data = dev_get_drvdata(dev);
2538 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2539 int nr = sattr->nr;
2540 int point = sattr->index;
2541 unsigned long val;
2542 int err;
2543 u8 reg;
2544
2545 err = kstrtoul(buf, 10, &val);
2546 if (err < 0)
2547 return err;
2548 if (val > 255)
2549 return -EINVAL;
2550
2551 if (point == data->auto_pwm_num) {
2552 if (data->kind != nct6775 && !val)
2553 return -EINVAL;
2554 if (data->kind != nct6779 && val)
2555 val = 0xff;
2556 }
2557
2558 mutex_lock(&data->update_lock);
2559 data->auto_pwm[nr][point] = val;
2560 if (point < data->auto_pwm_num) {
2561 nct6775_write_value(data,
2562 NCT6775_AUTO_PWM(data, nr, point),
2563 data->auto_pwm[nr][point]);
2564 } else {
2565 switch (data->kind) {
2566 case nct6775:
2567 /* disable if needed (pwm == 0) */
2568 reg = nct6775_read_value(data,
2569 NCT6775_REG_CRITICAL_ENAB[nr]);
2570 if (val)
2571 reg |= 0x02;
2572 else
2573 reg &= ~0x02;
2574 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2575 reg);
2576 break;
2577 case nct6776:
2578 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002579 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002580 case nct6779:
Guenter Roeck6c009502012-07-01 08:23:15 -07002581 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002582 val);
2583 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002584 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002585 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002586 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002587 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002588 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002589 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002590 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002591 reg);
2592 break;
2593 }
2594 }
2595 mutex_unlock(&data->update_lock);
2596 return count;
2597}
2598
2599static ssize_t
2600show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2601{
2602 struct nct6775_data *data = nct6775_update_device(dev);
2603 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2604 int nr = sattr->nr;
2605 int point = sattr->index;
2606
2607 /*
2608 * We don't know for sure if the temperature is signed or unsigned.
2609 * Assume it is unsigned.
2610 */
2611 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2612}
2613
2614static ssize_t
2615store_auto_temp(struct device *dev, struct device_attribute *attr,
2616 const char *buf, size_t count)
2617{
2618 struct nct6775_data *data = dev_get_drvdata(dev);
2619 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2620 int nr = sattr->nr;
2621 int point = sattr->index;
2622 unsigned long val;
2623 int err;
2624
2625 err = kstrtoul(buf, 10, &val);
2626 if (err)
2627 return err;
2628 if (val > 255000)
2629 return -EINVAL;
2630
2631 mutex_lock(&data->update_lock);
2632 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2633 if (point < data->auto_pwm_num) {
2634 nct6775_write_value(data,
2635 NCT6775_AUTO_TEMP(data, nr, point),
2636 data->auto_temp[nr][point]);
2637 } else {
2638 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2639 data->auto_temp[nr][point]);
2640 }
2641 mutex_unlock(&data->update_lock);
2642 return count;
2643}
2644
Guenter Roeckf73cf632013-03-18 09:22:50 -07002645static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2646 struct attribute *attr, int index)
2647{
2648 struct device *dev = container_of(kobj, struct device, kobj);
2649 struct nct6775_data *data = dev_get_drvdata(dev);
2650 int pwm = index / 36; /* pwm index */
2651 int nr = index % 36; /* attribute index */
2652
2653 if (!(data->has_pwm & (1 << pwm)))
2654 return 0;
2655
2656 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2657 return 0;
2658 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2659 return 0;
2660 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2661 return 0;
2662
2663 if (nr >= 22 && nr <= 35) { /* auto point */
2664 int api = (nr - 22) / 2; /* auto point index */
2665
2666 if (api > data->auto_pwm_num)
2667 return 0;
2668 }
2669 return attr->mode;
2670}
2671
2672SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2673 show_fan_time, store_fan_time, 0, 0);
2674SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2675 show_fan_time, store_fan_time, 0, 1);
2676SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2677 show_fan_time, store_fan_time, 0, 2);
2678SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2679 store_pwm, 0, 1);
2680SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2681 store_pwm, 0, 2);
2682SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2683 show_temp_tolerance, store_temp_tolerance, 0, 0);
2684SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2685 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2686 0, 1);
2687
2688SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2689 0, 3);
2690
2691SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2692 store_pwm, 0, 4);
2693
2694SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2695 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2696SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2697 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2698
2699SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2700 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2701SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2702 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2703
2704SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2705 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2706SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2707 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2708
2709SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2710 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2711SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2712 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2713
2714SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2715 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2716SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2717 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2718
2719SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2720 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2721SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2722 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2723
2724SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2725 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2726SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2727 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2728
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002729/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002730 * nct6775_pwm_is_visible uses the index into the following array
2731 * to determine if attributes should be created or not.
2732 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002733 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002734static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2735 &sensor_dev_template_pwm,
2736 &sensor_dev_template_pwm_mode,
2737 &sensor_dev_template_pwm_enable,
2738 &sensor_dev_template_pwm_temp_sel,
2739 &sensor_dev_template_pwm_temp_tolerance,
2740 &sensor_dev_template_pwm_crit_temp_tolerance,
2741 &sensor_dev_template_pwm_target_temp,
2742 &sensor_dev_template_fan_target,
2743 &sensor_dev_template_fan_tolerance,
2744 &sensor_dev_template_pwm_stop_time,
2745 &sensor_dev_template_pwm_step_up_time,
2746 &sensor_dev_template_pwm_step_down_time,
2747 &sensor_dev_template_pwm_start,
2748 &sensor_dev_template_pwm_floor,
2749 &sensor_dev_template_pwm_weight_temp_sel,
2750 &sensor_dev_template_pwm_weight_temp_step,
2751 &sensor_dev_template_pwm_weight_temp_step_tol,
2752 &sensor_dev_template_pwm_weight_temp_step_base,
2753 &sensor_dev_template_pwm_weight_duty_step,
2754 &sensor_dev_template_pwm_max, /* 19 */
2755 &sensor_dev_template_pwm_step, /* 20 */
2756 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2757 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2758 &sensor_dev_template_pwm_auto_point1_temp,
2759 &sensor_dev_template_pwm_auto_point2_pwm,
2760 &sensor_dev_template_pwm_auto_point2_temp,
2761 &sensor_dev_template_pwm_auto_point3_pwm,
2762 &sensor_dev_template_pwm_auto_point3_temp,
2763 &sensor_dev_template_pwm_auto_point4_pwm,
2764 &sensor_dev_template_pwm_auto_point4_temp,
2765 &sensor_dev_template_pwm_auto_point5_pwm,
2766 &sensor_dev_template_pwm_auto_point5_temp,
2767 &sensor_dev_template_pwm_auto_point6_pwm,
2768 &sensor_dev_template_pwm_auto_point6_temp,
2769 &sensor_dev_template_pwm_auto_point7_pwm,
2770 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002771
Guenter Roeckf73cf632013-03-18 09:22:50 -07002772 NULL
2773};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002774
Guenter Roeckf73cf632013-03-18 09:22:50 -07002775static struct sensor_template_group nct6775_pwm_template_group = {
2776 .templates = nct6775_attributes_pwm_template,
2777 .is_visible = nct6775_pwm_is_visible,
2778 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002779};
2780
2781static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002782show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2783{
2784 struct nct6775_data *data = dev_get_drvdata(dev);
2785 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
2786}
2787
2788static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2789
Guenter Roecka6bd5872012-12-04 03:13:34 -08002790/* Case open detection */
2791
2792static ssize_t
2793clear_caseopen(struct device *dev, struct device_attribute *attr,
2794 const char *buf, size_t count)
2795{
2796 struct nct6775_data *data = dev_get_drvdata(dev);
2797 struct nct6775_sio_data *sio_data = dev->platform_data;
2798 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
2799 unsigned long val;
2800 u8 reg;
2801 int ret;
2802
2803 if (kstrtoul(buf, 10, &val) || val != 0)
2804 return -EINVAL;
2805
2806 mutex_lock(&data->update_lock);
2807
2808 /*
2809 * Use CR registers to clear caseopen status.
2810 * The CR registers are the same for all chips, and not all chips
2811 * support clearing the caseopen status through "regular" registers.
2812 */
2813 ret = superio_enter(sio_data->sioreg);
2814 if (ret) {
2815 count = ret;
2816 goto error;
2817 }
2818
2819 superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
2820 reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
2821 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
2822 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
2823 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
2824 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
2825 superio_exit(sio_data->sioreg);
2826
2827 data->valid = false; /* Force cache refresh */
2828error:
2829 mutex_unlock(&data->update_lock);
2830 return count;
2831}
2832
Guenter Roeckf73cf632013-03-18 09:22:50 -07002833static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
2834 clear_caseopen, INTRUSION_ALARM_BASE);
2835static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
2836 clear_caseopen, INTRUSION_ALARM_BASE + 1);
2837
2838static umode_t nct6775_other_is_visible(struct kobject *kobj,
2839 struct attribute *attr, int index)
2840{
2841 struct device *dev = container_of(kobj, struct device, kobj);
2842 struct nct6775_data *data = dev_get_drvdata(dev);
2843
2844 if (index == 1 && !data->have_vid)
2845 return 0;
2846
2847 if (index == 2 || index == 3) {
2848 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
2849 return 0;
2850 }
2851
2852 return attr->mode;
2853}
2854
2855/*
2856 * nct6775_other_is_visible uses the index into the following array
2857 * to determine if attributes should be created or not.
2858 * Any change in order or content must be matched.
2859 */
2860static struct attribute *nct6775_attributes_other[] = {
2861 &dev_attr_name.attr,
2862 &dev_attr_cpu0_vid.attr, /* 1 */
2863 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
2864 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
2865
2866 NULL
2867};
2868
2869static const struct attribute_group nct6775_group_other = {
2870 .attrs = nct6775_attributes_other,
2871 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08002872};
2873
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002874/*
2875 * Driver and device management
2876 */
2877
2878static void nct6775_device_remove_files(struct device *dev)
2879{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002880 struct nct6775_data *data = dev_get_drvdata(dev);
2881
Guenter Roeckf73cf632013-03-18 09:22:50 -07002882 if (data->group_pwm)
2883 sysfs_remove_group(&dev->kobj, data->group_pwm);
2884 if (data->group_in)
2885 sysfs_remove_group(&dev->kobj, data->group_in);
2886 if (data->group_fan)
2887 sysfs_remove_group(&dev->kobj, data->group_fan);
2888 if (data->group_temp)
2889 sysfs_remove_group(&dev->kobj, data->group_temp);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002890
Guenter Roeckf73cf632013-03-18 09:22:50 -07002891 sysfs_remove_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002892}
2893
2894/* Get the monitoring functions started */
2895static inline void nct6775_init_device(struct nct6775_data *data)
2896{
Guenter Roeckaa136e52012-12-04 03:26:05 -08002897 int i;
2898 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002899
2900 /* Start monitoring if needed */
2901 if (data->REG_CONFIG) {
2902 tmp = nct6775_read_value(data, data->REG_CONFIG);
2903 if (!(tmp & 0x01))
2904 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
2905 }
2906
Guenter Roeckaa136e52012-12-04 03:26:05 -08002907 /* Enable temperature sensors if needed */
2908 for (i = 0; i < NUM_TEMP; i++) {
2909 if (!(data->have_temp & (1 << i)))
2910 continue;
2911 if (!data->reg_temp_config[i])
2912 continue;
2913 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
2914 if (tmp & 0x01)
2915 nct6775_write_value(data, data->reg_temp_config[i],
2916 tmp & 0xfe);
2917 }
2918
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002919 /* Enable VBAT monitoring if needed */
2920 tmp = nct6775_read_value(data, data->REG_VBAT);
2921 if (!(tmp & 0x01))
2922 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08002923
2924 diode = nct6775_read_value(data, data->REG_DIODE);
2925
2926 for (i = 0; i < data->temp_fixed_num; i++) {
2927 if (!(data->have_temp_fixed & (1 << i)))
2928 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07002929 if ((tmp & (data->DIODE_MASK << i))) /* diode */
2930 data->temp_type[i]
2931 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08002932 else /* thermistor */
2933 data->temp_type[i] = 4;
2934 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002935}
2936
Guenter Roeckf73cf632013-03-18 09:22:50 -07002937static void
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002938nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
2939 struct nct6775_data *data)
2940{
2941 int regval;
2942 bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002943 bool pwm3pin, pwm4pin, pwm5pin;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002944
2945 /* fan4 and fan5 share some pins with the GPIO and serial flash */
2946 if (data->kind == nct6775) {
2947 regval = superio_inb(sio_data->sioreg, 0x2c);
2948
2949 fan3pin = regval & (1 << 6);
2950 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002951 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002952
2953 /* On NCT6775, fan4 shares pins with the fdc interface */
2954 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
2955 fan4min = 0;
2956 fan5pin = 0;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002957 pwm4pin = 0;
2958 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002959 } else if (data->kind == nct6776) {
2960 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
2961
2962 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
2963 regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
2964
2965 if (regval & 0x80)
2966 fan3pin = gpok;
2967 else
2968 fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
2969
2970 if (regval & 0x40)
2971 fan4pin = gpok;
2972 else
2973 fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
2974
2975 if (regval & 0x20)
2976 fan5pin = gpok;
2977 else
2978 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
2979
2980 fan4min = fan4pin;
2981 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002982 pwm3pin = fan3pin;
2983 pwm4pin = 0;
2984 pwm5pin = 0;
Guenter Roeck6c009502012-07-01 08:23:15 -07002985 } else if (data->kind == nct6106) {
2986 regval = superio_inb(sio_data->sioreg, 0x24);
2987 fan3pin = !(regval & 0x80);
2988 pwm3pin = regval & 0x08;
2989 fan3min = fan3pin;
2990
2991 fan4pin = false;
2992 fan4min = false;
2993 fan5pin = false;
2994 pwm4pin = false;
2995 pwm5pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002996 } else { /* NCT6779D */
2997 regval = superio_inb(sio_data->sioreg, 0x1c);
2998
2999 fan3pin = !(regval & (1 << 5));
3000 fan4pin = !(regval & (1 << 6));
3001 fan5pin = !(regval & (1 << 7));
3002
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003003 pwm3pin = !(regval & (1 << 0));
3004 pwm4pin = !(regval & (1 << 1));
3005 pwm5pin = !(regval & (1 << 2));
3006
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003007 fan3min = fan3pin;
3008 fan4min = fan4pin;
3009 }
3010
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003011 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
3012 data->has_fan |= fan3pin << 2;
3013 data->has_fan_min |= fan3min << 2;
3014
3015 data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
3016 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
3017
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003018 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003019}
3020
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003021static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3022 int *available, int *mask)
3023{
3024 int i;
3025 u8 src;
3026
3027 for (i = 0; i < data->pwm_num && *available; i++) {
3028 int index;
3029
3030 if (!regp[i])
3031 continue;
3032 src = nct6775_read_value(data, regp[i]);
3033 src &= 0x1f;
3034 if (!src || (*mask & (1 << src)))
3035 continue;
3036 if (src >= data->temp_label_num ||
3037 !strlen(data->temp_label[src]))
3038 continue;
3039
3040 index = __ffs(*available);
3041 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3042 *available &= ~(1 << index);
3043 *mask |= 1 << src;
3044 }
3045}
3046
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003047static int nct6775_probe(struct platform_device *pdev)
3048{
3049 struct device *dev = &pdev->dev;
3050 struct nct6775_sio_data *sio_data = dev->platform_data;
3051 struct nct6775_data *data;
3052 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003053 int i, s, err = 0;
3054 int src, mask, available;
3055 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3056 const u16 *reg_temp_alternate, *reg_temp_crit;
3057 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003058 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003059 struct attribute_group *group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003060
3061 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3062 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3063 DRVNAME))
3064 return -EBUSY;
3065
3066 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3067 GFP_KERNEL);
3068 if (!data)
3069 return -ENOMEM;
3070
3071 data->kind = sio_data->kind;
3072 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003073 mutex_init(&data->update_lock);
3074 data->name = nct6775_device_names[data->kind];
3075 data->bank = 0xff; /* Force initial bank selection */
3076 platform_set_drvdata(pdev, data);
3077
3078 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003079 case nct6106:
3080 data->in_num = 9;
3081 data->pwm_num = 3;
3082 data->auto_pwm_num = 4;
3083 data->temp_fixed_num = 3;
3084 data->num_temp_alarms = 6;
3085
3086 data->fan_from_reg = fan_from_reg13;
3087 data->fan_from_reg_min = fan_from_reg13;
3088
3089 data->temp_label = nct6776_temp_label;
3090 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3091
3092 data->REG_VBAT = NCT6106_REG_VBAT;
3093 data->REG_DIODE = NCT6106_REG_DIODE;
3094 data->DIODE_MASK = NCT6106_DIODE_MASK;
3095 data->REG_VIN = NCT6106_REG_IN;
3096 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3097 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3098 data->REG_TARGET = NCT6106_REG_TARGET;
3099 data->REG_FAN = NCT6106_REG_FAN;
3100 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3101 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3102 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3103 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3104 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3105 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3106 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3107 data->REG_PWM[0] = NCT6106_REG_PWM;
3108 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3109 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3110 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3111 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3112 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3113 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3114 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3115 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3116 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3117 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3118 data->REG_CRITICAL_TEMP_TOLERANCE
3119 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3120 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3121 data->CRITICAL_PWM_ENABLE_MASK
3122 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3123 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3124 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3125 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3126 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3127 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3128 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3129 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3130 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3131 data->REG_ALARM = NCT6106_REG_ALARM;
3132 data->ALARM_BITS = NCT6106_ALARM_BITS;
3133
3134 reg_temp = NCT6106_REG_TEMP;
3135 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3136 reg_temp_over = NCT6106_REG_TEMP_OVER;
3137 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3138 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3139 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3140 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
3141
3142 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003143 case nct6775:
3144 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003145 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003146 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003147 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003148 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003149 data->num_temp_alarms = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003150
3151 data->ALARM_BITS = NCT6775_ALARM_BITS;
3152
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003153 data->fan_from_reg = fan_from_reg16;
3154 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003155 data->target_temp_mask = 0x7f;
3156 data->tolerance_mask = 0x0f;
3157 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003158
Guenter Roeckaa136e52012-12-04 03:26:05 -08003159 data->temp_label = nct6775_temp_label;
3160 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3161
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003162 data->REG_CONFIG = NCT6775_REG_CONFIG;
3163 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003164 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003165 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003166 data->REG_VIN = NCT6775_REG_IN;
3167 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3168 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003169 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003170 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003171 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003172 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003173 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003174 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003175 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3176 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3177 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003178 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003179 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3180 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3181 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3182 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003183 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003184 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3185 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3186 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003187 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3188 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3189 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3190 data->REG_CRITICAL_TEMP_TOLERANCE
3191 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003192 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3193 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003194 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003195 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3196 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3197 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3198 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003199 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003200
3201 reg_temp = NCT6775_REG_TEMP;
3202 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3203 reg_temp_over = NCT6775_REG_TEMP_OVER;
3204 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3205 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3206 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3207 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3208
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003209 break;
3210 case nct6776:
3211 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003212 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003213 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003214 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003215 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003216 data->num_temp_alarms = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003217
3218 data->ALARM_BITS = NCT6776_ALARM_BITS;
3219
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003220 data->fan_from_reg = fan_from_reg13;
3221 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003222 data->target_temp_mask = 0xff;
3223 data->tolerance_mask = 0x07;
3224 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003225
Guenter Roeckaa136e52012-12-04 03:26:05 -08003226 data->temp_label = nct6776_temp_label;
3227 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3228
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003229 data->REG_CONFIG = NCT6775_REG_CONFIG;
3230 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003231 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003232 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003233 data->REG_VIN = NCT6775_REG_IN;
3234 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3235 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003236 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003237 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003238 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003239 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003240 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003241 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003242 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3243 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3244 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3245 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003246 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003247 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3248 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003249 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3250 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003251 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3252 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3253 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003254 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3255 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3256 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3257 data->REG_CRITICAL_TEMP_TOLERANCE
3258 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003259 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3260 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003261 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003262 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3263 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3264 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3265 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003266 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003267
3268 reg_temp = NCT6775_REG_TEMP;
3269 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3270 reg_temp_over = NCT6775_REG_TEMP_OVER;
3271 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3272 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3273 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3274 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3275
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003276 break;
3277 case nct6779:
3278 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003279 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003280 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003281 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003282 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003283 data->num_temp_alarms = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003284
3285 data->ALARM_BITS = NCT6779_ALARM_BITS;
3286
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003287 data->fan_from_reg = fan_from_reg13;
3288 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003289 data->target_temp_mask = 0xff;
3290 data->tolerance_mask = 0x07;
3291 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003292
Guenter Roeckaa136e52012-12-04 03:26:05 -08003293 data->temp_label = nct6779_temp_label;
3294 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3295
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003296 data->REG_CONFIG = NCT6775_REG_CONFIG;
3297 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003298 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003299 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003300 data->REG_VIN = NCT6779_REG_IN;
3301 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3302 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003303 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003304 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003305 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003306 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003307 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003308 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003309 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3310 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3311 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3312 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003313 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003314 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3315 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003316 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3317 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003318 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3319 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3320 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003321 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3322 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3323 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3324 data->REG_CRITICAL_TEMP_TOLERANCE
3325 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003326 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3327 data->CRITICAL_PWM_ENABLE_MASK
3328 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3329 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003330 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3331 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003332 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003333 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3334 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3335 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3336 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003337 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003338
3339 reg_temp = NCT6779_REG_TEMP;
3340 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3341 reg_temp_over = NCT6779_REG_TEMP_OVER;
3342 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3343 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3344 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3345 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3346
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003347 break;
3348 default:
3349 return -ENODEV;
3350 }
3351 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003352 data->have_temp = 0;
3353
3354 /*
3355 * On some boards, not all available temperature sources are monitored,
3356 * even though some of the monitoring registers are unused.
3357 * Get list of unused monitoring registers, then detect if any fan
3358 * controls are configured to use unmonitored temperature sources.
3359 * If so, assign the unmonitored temperature sources to available
3360 * monitoring registers.
3361 */
3362 mask = 0;
3363 available = 0;
3364 for (i = 0; i < num_reg_temp; i++) {
3365 if (reg_temp[i] == 0)
3366 continue;
3367
3368 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3369 if (!src || (mask & (1 << src)))
3370 available |= 1 << i;
3371
3372 mask |= 1 << src;
3373 }
3374
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003375 /*
3376 * Now find unmonitored temperature registers and enable monitoring
3377 * if additional monitoring registers are available.
3378 */
3379 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3380 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3381
Guenter Roeckaa136e52012-12-04 03:26:05 -08003382 mask = 0;
3383 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3384 for (i = 0; i < num_reg_temp; i++) {
3385 if (reg_temp[i] == 0)
3386 continue;
3387
3388 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3389 if (!src || (mask & (1 << src)))
3390 continue;
3391
3392 if (src >= data->temp_label_num ||
3393 !strlen(data->temp_label[src])) {
3394 dev_info(dev,
3395 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3396 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3397 continue;
3398 }
3399
3400 mask |= 1 << src;
3401
3402 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3403 if (src <= data->temp_fixed_num) {
3404 data->have_temp |= 1 << (src - 1);
3405 data->have_temp_fixed |= 1 << (src - 1);
3406 data->reg_temp[0][src - 1] = reg_temp[i];
3407 data->reg_temp[1][src - 1] = reg_temp_over[i];
3408 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
3409 data->reg_temp_config[src - 1] = reg_temp_config[i];
3410 data->temp_src[src - 1] = src;
3411 continue;
3412 }
3413
3414 if (s >= NUM_TEMP)
3415 continue;
3416
3417 /* Use dynamic index for other sources */
3418 data->have_temp |= 1 << s;
3419 data->reg_temp[0][s] = reg_temp[i];
3420 data->reg_temp[1][s] = reg_temp_over[i];
3421 data->reg_temp[2][s] = reg_temp_hyst[i];
3422 data->reg_temp_config[s] = reg_temp_config[i];
3423 if (reg_temp_crit[src - 1])
3424 data->reg_temp[3][s] = reg_temp_crit[src - 1];
3425
3426 data->temp_src[s] = src;
3427 s++;
3428 }
3429
3430#ifdef USE_ALTERNATE
3431 /*
3432 * Go through the list of alternate temp registers and enable
3433 * if possible.
3434 * The temperature is already monitored if the respective bit in <mask>
3435 * is set.
3436 */
3437 for (i = 0; i < data->temp_label_num - 1; i++) {
3438 if (!reg_temp_alternate[i])
3439 continue;
3440 if (mask & (1 << (i + 1)))
3441 continue;
3442 if (i < data->temp_fixed_num) {
3443 if (data->have_temp & (1 << i))
3444 continue;
3445 data->have_temp |= 1 << i;
3446 data->have_temp_fixed |= 1 << i;
3447 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05cd2013-05-09 10:40:01 -07003448 if (i < num_reg_temp) {
3449 data->reg_temp[1][i] = reg_temp_over[i];
3450 data->reg_temp[2][i] = reg_temp_hyst[i];
3451 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003452 data->temp_src[i] = i + 1;
3453 continue;
3454 }
3455
3456 if (s >= NUM_TEMP) /* Abort if no more space */
3457 break;
3458
3459 data->have_temp |= 1 << s;
3460 data->reg_temp[0][s] = reg_temp_alternate[i];
3461 data->temp_src[s] = i + 1;
3462 s++;
3463 }
3464#endif /* USE_ALTERNATE */
3465
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003466 /* Initialize the chip */
3467 nct6775_init_device(data);
3468
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003469 err = superio_enter(sio_data->sioreg);
3470 if (err)
3471 return err;
3472
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003473 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3474 switch (data->kind) {
3475 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003476 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003477 break;
3478 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003479 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003480 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003481 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003482 case nct6779:
3483 break;
3484 }
3485
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003486 /*
3487 * Read VID value
3488 * We can get the VID input values directly at logical device D 0xe3.
3489 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003490 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003491 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3492 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3493 data->vrm = vid_which_vrm();
3494 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003495
3496 if (fan_debounce) {
3497 u8 tmp;
3498
3499 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3500 tmp = superio_inb(sio_data->sioreg,
3501 NCT6775_REG_CR_FAN_DEBOUNCE);
3502 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003503 case nct6106:
3504 tmp |= 0xe0;
3505 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003506 case nct6775:
3507 tmp |= 0x1e;
3508 break;
3509 case nct6776:
3510 case nct6779:
3511 tmp |= 0x3e;
3512 break;
3513 }
3514 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3515 tmp);
3516 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3517 data->name);
3518 }
3519
Guenter Roeckf73cf632013-03-18 09:22:50 -07003520 nct6775_check_fan_inputs(sio_data, data);
3521
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003522 superio_exit(sio_data->sioreg);
3523
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003524 /* Read fan clock dividers immediately */
3525 nct6775_init_fan_common(dev, data);
3526
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003527 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003528 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3529 data->pwm_num);
3530 if (IS_ERR(group)) {
3531 err = PTR_ERR(group);
3532 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003533 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003534 data->group_pwm = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003535
Guenter Roeckf73cf632013-03-18 09:22:50 -07003536 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3537 fls(data->have_in));
3538 if (IS_ERR(group)) {
3539 err = PTR_ERR(group);
3540 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003541 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003542 data->group_in = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003543
Guenter Roeckf73cf632013-03-18 09:22:50 -07003544 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3545 fls(data->has_fan));
3546 if (IS_ERR(group)) {
3547 err = PTR_ERR(group);
3548 goto exit_remove;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003549 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003550 data->group_fan = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003551
Guenter Roeckf73cf632013-03-18 09:22:50 -07003552 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3553 fls(data->have_temp));
3554 if (IS_ERR(group)) {
3555 err = PTR_ERR(group);
3556 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003557 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003558 data->group_temp = group;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003559
Guenter Roeckf73cf632013-03-18 09:22:50 -07003560 err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003561 if (err)
3562 goto exit_remove;
3563
3564 data->hwmon_dev = hwmon_device_register(dev);
3565 if (IS_ERR(data->hwmon_dev)) {
3566 err = PTR_ERR(data->hwmon_dev);
3567 goto exit_remove;
3568 }
3569
3570 return 0;
3571
3572exit_remove:
3573 nct6775_device_remove_files(dev);
3574 return err;
3575}
3576
3577static int nct6775_remove(struct platform_device *pdev)
3578{
3579 struct nct6775_data *data = platform_get_drvdata(pdev);
3580
3581 hwmon_device_unregister(data->hwmon_dev);
3582 nct6775_device_remove_files(&pdev->dev);
3583
3584 return 0;
3585}
3586
Guenter Roeck84d19d92012-12-04 08:01:39 -08003587#ifdef CONFIG_PM
3588static int nct6775_suspend(struct device *dev)
3589{
3590 struct nct6775_data *data = nct6775_update_device(dev);
3591 struct nct6775_sio_data *sio_data = dev->platform_data;
3592
3593 mutex_lock(&data->update_lock);
3594 data->vbat = nct6775_read_value(data, data->REG_VBAT);
3595 if (sio_data->kind == nct6775) {
3596 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3597 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3598 }
3599 mutex_unlock(&data->update_lock);
3600
3601 return 0;
3602}
3603
3604static int nct6775_resume(struct device *dev)
3605{
3606 struct nct6775_data *data = dev_get_drvdata(dev);
3607 struct nct6775_sio_data *sio_data = dev->platform_data;
3608 int i, j;
3609
3610 mutex_lock(&data->update_lock);
3611 data->bank = 0xff; /* Force initial bank selection */
3612
3613 /* Restore limits */
3614 for (i = 0; i < data->in_num; i++) {
3615 if (!(data->have_in & (1 << i)))
3616 continue;
3617
3618 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3619 data->in[i][1]);
3620 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3621 data->in[i][2]);
3622 }
3623
Guenter Roeckc409fd42013-04-09 05:04:00 -07003624 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003625 if (!(data->has_fan_min & (1 << i)))
3626 continue;
3627
3628 nct6775_write_value(data, data->REG_FAN_MIN[i],
3629 data->fan_min[i]);
3630 }
3631
3632 for (i = 0; i < NUM_TEMP; i++) {
3633 if (!(data->have_temp & (1 << i)))
3634 continue;
3635
Guenter Roeckc409fd42013-04-09 05:04:00 -07003636 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003637 if (data->reg_temp[j][i])
3638 nct6775_write_temp(data, data->reg_temp[j][i],
3639 data->temp[j][i]);
3640 }
3641
3642 /* Restore other settings */
3643 nct6775_write_value(data, data->REG_VBAT, data->vbat);
3644 if (sio_data->kind == nct6775) {
3645 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3646 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3647 }
3648
3649 /* Force re-reading all values */
3650 data->valid = false;
3651 mutex_unlock(&data->update_lock);
3652
3653 return 0;
3654}
3655
3656static const struct dev_pm_ops nct6775_dev_pm_ops = {
3657 .suspend = nct6775_suspend,
3658 .resume = nct6775_resume,
3659};
3660
3661#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
3662#else
3663#define NCT6775_DEV_PM_OPS NULL
3664#endif /* CONFIG_PM */
3665
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003666static struct platform_driver nct6775_driver = {
3667 .driver = {
3668 .owner = THIS_MODULE,
3669 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08003670 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003671 },
3672 .probe = nct6775_probe,
3673 .remove = nct6775_remove,
3674};
3675
Guenter Roeck6d4b3622013-04-21 09:08:11 -07003676static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07003677 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07003678 "NCT6775F",
3679 "NCT6776D/F",
3680 "NCT6779D",
3681};
3682
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003683/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003684static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003685{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003686 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003687 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003688 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003689
3690 err = superio_enter(sioaddr);
3691 if (err)
3692 return err;
3693
3694 if (force_id)
3695 val = force_id;
3696 else
3697 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
3698 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
3699 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003700 case SIO_NCT6106_ID:
3701 sio_data->kind = nct6106;
3702 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003703 case SIO_NCT6775_ID:
3704 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003705 break;
3706 case SIO_NCT6776_ID:
3707 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003708 break;
3709 case SIO_NCT6779_ID:
3710 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003711 break;
3712 default:
3713 if (val != 0xffff)
3714 pr_debug("unsupported chip ID: 0x%04x\n", val);
3715 superio_exit(sioaddr);
3716 return -ENODEV;
3717 }
3718
3719 /* We have a known chip, find the HWM I/O address */
3720 superio_select(sioaddr, NCT6775_LD_HWM);
3721 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
3722 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07003723 addr = val & IOREGION_ALIGNMENT;
3724 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003725 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
3726 superio_exit(sioaddr);
3727 return -ENODEV;
3728 }
3729
3730 /* Activate logical device if needed */
3731 val = superio_inb(sioaddr, SIO_REG_ENABLE);
3732 if (!(val & 0x01)) {
3733 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
3734 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
3735 }
3736
3737 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07003738 pr_info("Found %s or compatible chip at %#x:%#x\n",
3739 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003740 sio_data->sioreg = sioaddr;
3741
Guenter Roeck698a7c22013-04-05 07:35:25 -07003742 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003743}
3744
3745/*
3746 * when Super-I/O functions move to a separate file, the Super-I/O
3747 * bus will manage the lifetime of the device and this module will only keep
3748 * track of the nct6775 driver. But since we platform_device_alloc(), we
3749 * must keep track of the device
3750 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003751static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003752
3753static int __init sensors_nct6775_init(void)
3754{
Guenter Roeck698a7c22013-04-05 07:35:25 -07003755 int i, err;
3756 bool found = false;
3757 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003758 struct resource res;
3759 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003760 int sioaddr[2] = { 0x2e, 0x4e };
3761
3762 err = platform_driver_register(&nct6775_driver);
3763 if (err)
3764 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003765
3766 /*
3767 * initialize sio_data->kind and sio_data->sioreg.
3768 *
3769 * when Super-I/O functions move to a separate file, the Super-I/O
3770 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
3771 * nct6775 hardware monitor, and call probe()
3772 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003773 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3774 address = nct6775_find(sioaddr[i], &sio_data);
3775 if (address <= 0)
3776 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003777
Guenter Roeck698a7c22013-04-05 07:35:25 -07003778 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003779
Guenter Roeck698a7c22013-04-05 07:35:25 -07003780 pdev[i] = platform_device_alloc(DRVNAME, address);
3781 if (!pdev[i]) {
3782 err = -ENOMEM;
3783 goto exit_device_put;
3784 }
3785
3786 err = platform_device_add_data(pdev[i], &sio_data,
3787 sizeof(struct nct6775_sio_data));
3788 if (err)
3789 goto exit_device_put;
3790
3791 memset(&res, 0, sizeof(res));
3792 res.name = DRVNAME;
3793 res.start = address + IOREGION_OFFSET;
3794 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
3795 res.flags = IORESOURCE_IO;
3796
3797 err = acpi_check_resource_conflict(&res);
3798 if (err) {
3799 platform_device_put(pdev[i]);
3800 pdev[i] = NULL;
3801 continue;
3802 }
3803
3804 err = platform_device_add_resources(pdev[i], &res, 1);
3805 if (err)
3806 goto exit_device_put;
3807
3808 /* platform_device_add calls probe() */
3809 err = platform_device_add(pdev[i]);
3810 if (err)
3811 goto exit_device_put;
3812 }
3813 if (!found) {
3814 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003815 goto exit_unregister;
3816 }
3817
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003818 return 0;
3819
3820exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07003821 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3822 if (pdev[i])
3823 platform_device_put(pdev[i]);
3824 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003825exit_unregister:
3826 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003827 return err;
3828}
3829
3830static void __exit sensors_nct6775_exit(void)
3831{
Guenter Roeck698a7c22013-04-05 07:35:25 -07003832 int i;
3833
3834 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3835 if (pdev[i])
3836 platform_device_unregister(pdev[i]);
3837 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003838 platform_driver_unregister(&nct6775_driver);
3839}
3840
3841MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
3842MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
3843MODULE_LICENSE("GPL");
3844
3845module_init(sensors_nct6775_init);
3846module_exit(sensors_nct6775_exit);