blob: f43f5e571db97a9b178f76a88ef82e8414c9ff39 [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
36 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
37 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
38 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
39 *
40 * #temp lists the number of monitored temperature sources (first value) plus
41 * the number of directly connectable temperature sensors (second value).
42 */
43
44#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
45
46#include <linux/module.h>
47#include <linux/init.h>
48#include <linux/slab.h>
49#include <linux/jiffies.h>
50#include <linux/platform_device.h>
51#include <linux/hwmon.h>
52#include <linux/hwmon-sysfs.h>
53#include <linux/hwmon-vid.h>
54#include <linux/err.h>
55#include <linux/mutex.h>
56#include <linux/acpi.h>
57#include <linux/io.h>
58#include "lm75.h"
59
Guenter Roeckaa136e52012-12-04 03:26:05 -080060#define USE_ALTERNATE
61
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070062enum kinds { nct6775, nct6776, nct6779 };
63
64/* used to set data->name = nct6775_device_names[data->sio_kind] */
65static const char * const nct6775_device_names[] = {
66 "nct6775",
67 "nct6776",
68 "nct6779",
69};
70
71static unsigned short force_id;
72module_param(force_id, ushort, 0);
73MODULE_PARM_DESC(force_id, "Override the detected device ID");
74
Guenter Roeck47ece962012-12-04 07:59:32 -080075static unsigned short fan_debounce;
76module_param(fan_debounce, ushort, 0);
77MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
78
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070079#define DRVNAME "nct6775"
80
81/*
82 * Super-I/O constants and functions
83 */
84
Guenter Roecka6bd5872012-12-04 03:13:34 -080085#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070086#define NCT6775_LD_HWM 0x0b
87#define NCT6775_LD_VID 0x0d
88
89#define SIO_REG_LDSEL 0x07 /* Logical device select */
90#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
91#define SIO_REG_ENABLE 0x30 /* Logical device enable */
92#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
93
94#define SIO_NCT6775_ID 0xb470
95#define SIO_NCT6776_ID 0xc330
96#define SIO_NCT6779_ID 0xc560
97#define SIO_ID_MASK 0xFFF0
98
Guenter Roeck77eb5b32012-12-04 08:30:54 -080099enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
100
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700101static inline void
102superio_outb(int ioreg, int reg, int val)
103{
104 outb(reg, ioreg);
105 outb(val, ioreg + 1);
106}
107
108static inline int
109superio_inb(int ioreg, int reg)
110{
111 outb(reg, ioreg);
112 return inb(ioreg + 1);
113}
114
115static inline void
116superio_select(int ioreg, int ld)
117{
118 outb(SIO_REG_LDSEL, ioreg);
119 outb(ld, ioreg + 1);
120}
121
122static inline int
123superio_enter(int ioreg)
124{
125 /*
126 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
127 */
128 if (!request_muxed_region(ioreg, 2, DRVNAME))
129 return -EBUSY;
130
131 outb(0x87, ioreg);
132 outb(0x87, ioreg);
133
134 return 0;
135}
136
137static inline void
138superio_exit(int ioreg)
139{
140 outb(0xaa, ioreg);
141 outb(0x02, ioreg);
142 outb(0x02, ioreg + 1);
143 release_region(ioreg, 2);
144}
145
146/*
147 * ISA constants
148 */
149
150#define IOREGION_ALIGNMENT (~7)
151#define IOREGION_OFFSET 5
152#define IOREGION_LENGTH 2
153#define ADDR_REG_OFFSET 0
154#define DATA_REG_OFFSET 1
155
156#define NCT6775_REG_BANK 0x4E
157#define NCT6775_REG_CONFIG 0x40
158
159/*
160 * Not currently used:
161 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
162 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
163 * REG_MAN_ID is at port 0x4f
164 * REG_CHIP_ID is at port 0x58
165 */
166
Guenter Roeckaa136e52012-12-04 03:26:05 -0800167#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
168#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
169
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700170#define NUM_REG_ALARM 4 /* Max number of alarm registers */
171
172/* Common and NCT6775 specific data */
173
174/* Voltage min/max registers for nr=7..14 are in bank 5 */
175
176static const u16 NCT6775_REG_IN_MAX[] = {
177 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
178 0x55c, 0x55e, 0x560, 0x562 };
179static const u16 NCT6775_REG_IN_MIN[] = {
180 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
181 0x55d, 0x55f, 0x561, 0x563 };
182static const u16 NCT6775_REG_IN[] = {
183 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
184};
185
186#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800187#define NCT6775_REG_DIODE 0x5E
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700188
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800189#define NCT6775_REG_FANDIV1 0x506
190#define NCT6775_REG_FANDIV2 0x507
191
Guenter Roeck47ece962012-12-04 07:59:32 -0800192#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
193
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700194static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
195
196/* 0..15 voltages, 16..23 fans, 24..31 temperatures */
197
198static const s8 NCT6775_ALARM_BITS[] = {
199 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
200 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
201 -1, /* unused */
202 6, 7, 11, 10, 23, /* fan1..fan5 */
203 -1, -1, -1, /* unused */
204 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
205 12, -1 }; /* intrusion0, intrusion1 */
206
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800207#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800208#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800209#define INTRUSION_ALARM_BASE 30
210
211static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
212static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
213
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800214/* DC or PWM output fan configuration */
215static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
216static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
217
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800218/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800219
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800220static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
221static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
222static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
223 0x103, 0x203, 0x303, 0x803, 0x903 };
224static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
225 0x104, 0x204, 0x304, 0x804, 0x904 };
226static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
227 0x105, 0x205, 0x305, 0x805, 0x905 };
228static const u16 NCT6775_REG_FAN_START_OUTPUT[]
229 = { 0x106, 0x206, 0x306, 0x806, 0x906 };
230static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
231static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
232
233static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
234 0x107, 0x207, 0x307, 0x807, 0x907 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800235static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
236static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
237
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800238static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
239static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800240static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800241
Guenter Roeckaa136e52012-12-04 03:26:05 -0800242static const u16 NCT6775_REG_TEMP[] = {
243 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
244
245static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
246 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
247static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
248 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
249static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
250 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
251
252static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
253 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
254
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800255static const u16 NCT6775_REG_TEMP_SEL[] = {
256 0x100, 0x200, 0x300, 0x800, 0x900 };
257
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800258static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
259 0x139, 0x239, 0x339, 0x839, 0x939 };
260static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
261 0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
262static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
263 0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
264static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
265 0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
266static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
267 0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
268
Guenter Roeckaa136e52012-12-04 03:26:05 -0800269static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
270
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800271static const u16 NCT6775_REG_AUTO_TEMP[] = {
272 0x121, 0x221, 0x321, 0x821, 0x921 };
273static const u16 NCT6775_REG_AUTO_PWM[] = {
274 0x127, 0x227, 0x327, 0x827, 0x927 };
275
276#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
277#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
278
279static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
280
281static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
282 0x135, 0x235, 0x335, 0x835, 0x935 };
283static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
284 0x138, 0x238, 0x338, 0x838, 0x938 };
285
Guenter Roeckaa136e52012-12-04 03:26:05 -0800286static const char *const nct6775_temp_label[] = {
287 "",
288 "SYSTIN",
289 "CPUTIN",
290 "AUXTIN",
291 "AMD SB-TSI",
292 "PECI Agent 0",
293 "PECI Agent 1",
294 "PECI Agent 2",
295 "PECI Agent 3",
296 "PECI Agent 4",
297 "PECI Agent 5",
298 "PECI Agent 6",
299 "PECI Agent 7",
300 "PCH_CHIP_CPU_MAX_TEMP",
301 "PCH_CHIP_TEMP",
302 "PCH_CPU_TEMP",
303 "PCH_MCH_TEMP",
304 "PCH_DIM0_TEMP",
305 "PCH_DIM1_TEMP",
306 "PCH_DIM2_TEMP",
307 "PCH_DIM3_TEMP"
308};
309
310static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
311 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
312
313static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
314 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
315 0xa07 };
316
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700317/* NCT6776 specific data */
318
319static const s8 NCT6776_ALARM_BITS[] = {
320 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
321 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
322 -1, /* unused */
323 6, 7, 11, 10, 23, /* fan1..fan5 */
324 -1, -1, -1, /* unused */
325 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
326 12, 9 }; /* intrusion0, intrusion1 */
327
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800328static const u16 NCT6776_REG_TOLERANCE_H[] = {
329 0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
330
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800331static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
332static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
333
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800334static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800335static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800336
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800337static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
338 0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
339
Guenter Roeckaa136e52012-12-04 03:26:05 -0800340static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
341 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
342
343static const char *const nct6776_temp_label[] = {
344 "",
345 "SYSTIN",
346 "CPUTIN",
347 "AUXTIN",
348 "SMBUSMASTER 0",
349 "SMBUSMASTER 1",
350 "SMBUSMASTER 2",
351 "SMBUSMASTER 3",
352 "SMBUSMASTER 4",
353 "SMBUSMASTER 5",
354 "SMBUSMASTER 6",
355 "SMBUSMASTER 7",
356 "PECI Agent 0",
357 "PECI Agent 1",
358 "PCH_CHIP_CPU_MAX_TEMP",
359 "PCH_CHIP_TEMP",
360 "PCH_CPU_TEMP",
361 "PCH_MCH_TEMP",
362 "PCH_DIM0_TEMP",
363 "PCH_DIM1_TEMP",
364 "PCH_DIM2_TEMP",
365 "PCH_DIM3_TEMP",
366 "BYTE_TEMP"
367};
368
369static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
370 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
371
372static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
373 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
374
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700375/* NCT6779 specific data */
376
377static const u16 NCT6779_REG_IN[] = {
378 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
379 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
380
381static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
382 0x459, 0x45A, 0x45B, 0x568 };
383
384static const s8 NCT6779_ALARM_BITS[] = {
385 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
386 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
387 -1, /* unused */
388 6, 7, 11, 10, 23, /* fan1..fan5 */
389 -1, -1, -1, /* unused */
390 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
391 12, 9 }; /* intrusion0, intrusion1 */
392
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800393static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800394static const u16 NCT6779_REG_FAN_PULSES[] = {
395 0x644, 0x645, 0x646, 0x647, 0x648 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800396
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800397static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
398 0x136, 0x236, 0x336, 0x836, 0x936 };
399static const u16 NCT6779_REG_CRITICAL_PWM[] = {
400 0x137, 0x237, 0x337, 0x837, 0x937 };
401
Guenter Roeckaa136e52012-12-04 03:26:05 -0800402static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
403static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
404 0x18, 0x152 };
405static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
406 0x3a, 0x153 };
407static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
408 0x39, 0x155 };
409
410static const u16 NCT6779_REG_TEMP_OFFSET[] = {
411 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
412
413static const char *const nct6779_temp_label[] = {
414 "",
415 "SYSTIN",
416 "CPUTIN",
417 "AUXTIN0",
418 "AUXTIN1",
419 "AUXTIN2",
420 "AUXTIN3",
421 "",
422 "SMBUSMASTER 0",
423 "SMBUSMASTER 1",
424 "SMBUSMASTER 2",
425 "SMBUSMASTER 3",
426 "SMBUSMASTER 4",
427 "SMBUSMASTER 5",
428 "SMBUSMASTER 6",
429 "SMBUSMASTER 7",
430 "PECI Agent 0",
431 "PECI Agent 1",
432 "PCH_CHIP_CPU_MAX_TEMP",
433 "PCH_CHIP_TEMP",
434 "PCH_CPU_TEMP",
435 "PCH_MCH_TEMP",
436 "PCH_DIM0_TEMP",
437 "PCH_DIM1_TEMP",
438 "PCH_DIM2_TEMP",
439 "PCH_DIM3_TEMP",
440 "BYTE_TEMP"
441};
442
443static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
444 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
445 0, 0, 0, 0, 0, 0, 0, 0,
446 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
447 0x408, 0 };
448
449static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
450 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
451
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800452static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
453{
454 if (mode == 0 && pwm == 255)
455 return off;
456 return mode + 1;
457}
458
459static int pwm_enable_to_reg(enum pwm_enable mode)
460{
461 if (mode == off)
462 return 0;
463 return mode - 1;
464}
465
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700466/*
467 * Conversions
468 */
469
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800470/* 1 is DC mode, output in ms */
471static unsigned int step_time_from_reg(u8 reg, u8 mode)
472{
473 return mode ? 400 * reg : 100 * reg;
474}
475
476static u8 step_time_to_reg(unsigned int msec, u8 mode)
477{
478 return clamp_val((mode ? (msec + 200) / 400 :
479 (msec + 50) / 100), 1, 255);
480}
481
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800482static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
483{
484 if (reg == 0 || reg == 255)
485 return 0;
486 return 1350000U / (reg << divreg);
487}
488
489static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
490{
491 if ((reg & 0xff1f) == 0xff1f)
492 return 0;
493
494 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
495
496 if (reg == 0)
497 return 0;
498
499 return 1350000U / reg;
500}
501
502static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
503{
504 if (reg == 0 || reg == 0xffff)
505 return 0;
506
507 /*
508 * Even though the registers are 16 bit wide, the fan divisor
509 * still applies.
510 */
511 return 1350000U / (reg << divreg);
512}
513
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800514static u16 fan_to_reg(u32 fan, unsigned int divreg)
515{
516 if (!fan)
517 return 0;
518
519 return (1350000U / fan) >> divreg;
520}
521
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800522static inline unsigned int
523div_from_reg(u8 reg)
524{
525 return 1 << reg;
526}
527
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700528/*
529 * Some of the voltage inputs have internal scaling, the tables below
530 * contain 8 (the ADC LSB in mV) * scaling factor * 100
531 */
532static const u16 scale_in[15] = {
533 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
534 800, 800
535};
536
537static inline long in_from_reg(u8 reg, u8 nr)
538{
539 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
540}
541
542static inline u8 in_to_reg(u32 val, u8 nr)
543{
544 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
545}
546
547/*
548 * Data structures and manipulation thereof
549 */
550
551struct nct6775_data {
552 int addr; /* IO base of hw monitor block */
553 enum kinds kind;
554 const char *name;
555
556 struct device *hwmon_dev;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700557
Guenter Roeckaa136e52012-12-04 03:26:05 -0800558 u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
559 * 3=temp_crit
560 */
561 u8 temp_src[NUM_TEMP];
562 u16 reg_temp_config[NUM_TEMP];
563 const char * const *temp_label;
564 int temp_label_num;
565
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700566 u16 REG_CONFIG;
567 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800568 u16 REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700569
570 const s8 *ALARM_BITS;
571
572 const u16 *REG_VIN;
573 const u16 *REG_IN_MINMAX[2];
574
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800575 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800576 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800577 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800578 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800579 const u16 *REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800580 const u16 *REG_FAN_TIME[3];
581
582 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800583
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800584 const u8 *REG_PWM_MODE;
585 const u8 *PWM_MODE_MASK;
586
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800587 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
588 * [3]=pwm_max, [4]=pwm_step,
589 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800590 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800591 const u16 *REG_PWM_READ;
592
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800593 const u16 *REG_AUTO_TEMP;
594 const u16 *REG_AUTO_PWM;
595
596 const u16 *REG_CRITICAL_TEMP;
597 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
598
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800599 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800600 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800601 const u16 *REG_WEIGHT_TEMP_SEL;
602 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
603
Guenter Roeckaa136e52012-12-04 03:26:05 -0800604 const u16 *REG_TEMP_OFFSET;
605
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700606 const u16 *REG_ALARM;
607
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800608 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
609 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
610
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700611 struct mutex update_lock;
612 bool valid; /* true if following fields are valid */
613 unsigned long last_updated; /* In jiffies */
614
615 /* Register values */
616 u8 bank; /* current register bank */
617 u8 in_num; /* number of in inputs we have */
618 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800619 unsigned int rpm[5];
620 u16 fan_min[5];
Guenter Roeck5c25d952012-12-11 07:29:06 -0800621 u8 fan_pulses[5];
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800622 u8 fan_div[5];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800623 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800624 u8 has_fan; /* some fan inputs can be disabled */
625 u8 has_fan_min; /* some fans don't have min register */
626 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700627
Guenter Roeckaa136e52012-12-04 03:26:05 -0800628 u8 temp_fixed_num; /* 3 or 6 */
629 u8 temp_type[NUM_TEMP_FIXED];
630 s8 temp_offset[NUM_TEMP_FIXED];
631 s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
632 * 3=temp_crit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700633 u64 alarms;
634
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800635 u8 pwm_num; /* number of pwm */
636 u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
637 enum pwm_enable pwm_enable[5];
638 /* 0->off
639 * 1->manual
640 * 2->thermal cruise mode (also called SmartFan I)
641 * 3->fan speed cruise mode
642 * 4->SmartFan III
643 * 5->enhanced variable thermal cruise (SmartFan IV)
644 */
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800645 u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
646 * [3]=pwm_max, [4]=pwm_step,
647 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800648 */
649
650 u8 target_temp[5];
651 u8 target_temp_mask;
652 u32 target_speed[5];
653 u32 target_speed_tolerance[5];
654 u8 speed_tolerance_limit;
655
656 u8 temp_tolerance[2][5];
657 u8 tolerance_mask;
658
659 u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
660
661 /* Automatic fan speed control registers */
662 int auto_pwm_num;
663 u8 auto_pwm[5][7];
664 u8 auto_temp[5][7];
665 u8 pwm_temp_sel[5];
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800666 u8 pwm_weight_temp_sel[5];
667 u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol,
668 * 2->temp_base
669 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800670
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700671 u8 vid;
672 u8 vrm;
673
Guenter Roeckaa136e52012-12-04 03:26:05 -0800674 u16 have_temp;
675 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700676 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800677#ifdef CONFIG_PM
678 /* Remember extra register values over suspend/resume */
679 u8 vbat;
680 u8 fandiv1;
681 u8 fandiv2;
682#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700683};
684
685struct nct6775_sio_data {
686 int sioreg;
687 enum kinds kind;
688};
689
690static bool is_word_sized(struct nct6775_data *data, u16 reg)
691{
692 switch (data->kind) {
693 case nct6775:
694 return (((reg & 0xff00) == 0x100 ||
695 (reg & 0xff00) == 0x200) &&
696 ((reg & 0x00ff) == 0x50 ||
697 (reg & 0x00ff) == 0x53 ||
698 (reg & 0x00ff) == 0x55)) ||
699 (reg & 0xfff0) == 0x630 ||
700 reg == 0x640 || reg == 0x642 ||
701 reg == 0x662 ||
702 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
703 reg == 0x73 || reg == 0x75 || reg == 0x77;
704 case nct6776:
705 return (((reg & 0xff00) == 0x100 ||
706 (reg & 0xff00) == 0x200) &&
707 ((reg & 0x00ff) == 0x50 ||
708 (reg & 0x00ff) == 0x53 ||
709 (reg & 0x00ff) == 0x55)) ||
710 (reg & 0xfff0) == 0x630 ||
711 reg == 0x402 ||
712 reg == 0x640 || reg == 0x642 ||
713 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
714 reg == 0x73 || reg == 0x75 || reg == 0x77;
715 case nct6779:
716 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
717 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
718 reg == 0x402 ||
719 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
720 reg == 0x640 || reg == 0x642 ||
721 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
722 reg == 0x7b;
723 }
724 return false;
725}
726
727/*
728 * On older chips, only registers 0x50-0x5f are banked.
729 * On more recent chips, all registers are banked.
730 * Assume that is the case and set the bank number for each access.
731 * Cache the bank number so it only needs to be set if it changes.
732 */
733static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
734{
735 u8 bank = reg >> 8;
736 if (data->bank != bank) {
737 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
738 outb_p(bank, data->addr + DATA_REG_OFFSET);
739 data->bank = bank;
740 }
741}
742
743static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
744{
745 int res, word_sized = is_word_sized(data, reg);
746
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700747 nct6775_set_bank(data, reg);
748 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
749 res = inb_p(data->addr + DATA_REG_OFFSET);
750 if (word_sized) {
751 outb_p((reg & 0xff) + 1,
752 data->addr + ADDR_REG_OFFSET);
753 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
754 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700755 return res;
756}
757
758static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
759{
760 int word_sized = is_word_sized(data, reg);
761
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700762 nct6775_set_bank(data, reg);
763 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
764 if (word_sized) {
765 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
766 outb_p((reg & 0xff) + 1,
767 data->addr + ADDR_REG_OFFSET);
768 }
769 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700770 return 0;
771}
772
Guenter Roeckaa136e52012-12-04 03:26:05 -0800773/* We left-align 8-bit temperature values to make the code simpler */
774static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
775{
776 u16 res;
777
778 res = nct6775_read_value(data, reg);
779 if (!is_word_sized(data, reg))
780 res <<= 8;
781
782 return res;
783}
784
785static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
786{
787 if (!is_word_sized(data, reg))
788 value >>= 8;
789 return nct6775_write_value(data, reg, value);
790}
791
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800792/* This function assumes that the caller holds data->update_lock */
793static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
794{
795 u8 reg;
796
797 switch (nr) {
798 case 0:
799 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
800 | (data->fan_div[0] & 0x7);
801 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
802 break;
803 case 1:
804 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
805 | ((data->fan_div[1] << 4) & 0x70);
806 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
807 break;
808 case 2:
809 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
810 | (data->fan_div[2] & 0x7);
811 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
812 break;
813 case 3:
814 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
815 | ((data->fan_div[3] << 4) & 0x70);
816 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
817 break;
818 }
819}
820
821static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
822{
823 if (data->kind == nct6775)
824 nct6775_write_fan_div(data, nr);
825}
826
827static void nct6775_update_fan_div(struct nct6775_data *data)
828{
829 u8 i;
830
831 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
832 data->fan_div[0] = i & 0x7;
833 data->fan_div[1] = (i & 0x70) >> 4;
834 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
835 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -0700836 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800837 data->fan_div[3] = (i & 0x70) >> 4;
838}
839
840static void nct6775_update_fan_div_common(struct nct6775_data *data)
841{
842 if (data->kind == nct6775)
843 nct6775_update_fan_div(data);
844}
845
846static void nct6775_init_fan_div(struct nct6775_data *data)
847{
848 int i;
849
850 nct6775_update_fan_div_common(data);
851 /*
852 * For all fans, start with highest divider value if the divider
853 * register is not initialized. This ensures that we get a
854 * reading from the fan count register, even if it is not optimal.
855 * We'll compute a better divider later on.
856 */
Guenter Roeckc409fd42013-04-09 05:04:00 -0700857 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800858 if (!(data->has_fan & (1 << i)))
859 continue;
860 if (data->fan_div[i] == 0) {
861 data->fan_div[i] = 7;
862 nct6775_write_fan_div_common(data, i);
863 }
864 }
865}
866
867static void nct6775_init_fan_common(struct device *dev,
868 struct nct6775_data *data)
869{
870 int i;
871 u8 reg;
872
873 if (data->has_fan_div)
874 nct6775_init_fan_div(data);
875
876 /*
877 * If fan_min is not set (0), set it to 0xff to disable it. This
878 * prevents the unnecessary warning when fanX_min is reported as 0.
879 */
Guenter Roeckc409fd42013-04-09 05:04:00 -0700880 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800881 if (data->has_fan_min & (1 << i)) {
882 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
883 if (!reg)
884 nct6775_write_value(data, data->REG_FAN_MIN[i],
885 data->has_fan_div ? 0xff
886 : 0xff1f);
887 }
888 }
889}
890
891static void nct6775_select_fan_div(struct device *dev,
892 struct nct6775_data *data, int nr, u16 reg)
893{
894 u8 fan_div = data->fan_div[nr];
895 u16 fan_min;
896
897 if (!data->has_fan_div)
898 return;
899
900 /*
901 * If we failed to measure the fan speed, or the reported value is not
902 * in the optimal range, and the clock divider can be modified,
903 * let's try that for next time.
904 */
905 if (reg == 0x00 && fan_div < 0x07)
906 fan_div++;
907 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
908 fan_div--;
909
910 if (fan_div != data->fan_div[nr]) {
911 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
912 nr + 1, div_from_reg(data->fan_div[nr]),
913 div_from_reg(fan_div));
914
915 /* Preserve min limit if possible */
916 if (data->has_fan_min & (1 << nr)) {
917 fan_min = data->fan_min[nr];
918 if (fan_div > data->fan_div[nr]) {
919 if (fan_min != 255 && fan_min > 1)
920 fan_min >>= 1;
921 } else {
922 if (fan_min != 255) {
923 fan_min <<= 1;
924 if (fan_min > 254)
925 fan_min = 254;
926 }
927 }
928 if (fan_min != data->fan_min[nr]) {
929 data->fan_min[nr] = fan_min;
930 nct6775_write_value(data, data->REG_FAN_MIN[nr],
931 fan_min);
932 }
933 }
934 data->fan_div[nr] = fan_div;
935 nct6775_write_fan_div_common(data, nr);
936 }
937}
938
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800939static void nct6775_update_pwm(struct device *dev)
940{
941 struct nct6775_data *data = dev_get_drvdata(dev);
942 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800943 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800944 bool duty_is_dc;
945
946 for (i = 0; i < data->pwm_num; i++) {
947 if (!(data->has_pwm & (1 << i)))
948 continue;
949
950 duty_is_dc = data->REG_PWM_MODE[i] &&
951 (nct6775_read_value(data, data->REG_PWM_MODE[i])
952 & data->PWM_MODE_MASK[i]);
953 data->pwm_mode[i] = duty_is_dc;
954
955 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
956 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
957 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
958 data->pwm[j][i]
959 = nct6775_read_value(data,
960 data->REG_PWM[j][i]);
961 }
962 }
963
964 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
965 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800966
967 if (!data->temp_tolerance[0][i] ||
968 data->pwm_enable[i] != speed_cruise)
969 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
970 if (!data->target_speed_tolerance[i] ||
971 data->pwm_enable[i] == speed_cruise) {
972 u8 t = fanmodecfg & 0x0f;
973 if (data->REG_TOLERANCE_H) {
974 t |= (nct6775_read_value(data,
975 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
976 }
977 data->target_speed_tolerance[i] = t;
978 }
979
980 data->temp_tolerance[1][i] =
981 nct6775_read_value(data,
982 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
983
984 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
985 data->pwm_temp_sel[i] = reg & 0x1f;
986 /* If fan can stop, report floor as 0 */
987 if (reg & 0x80)
988 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800989
990 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
991 data->pwm_weight_temp_sel[i] = reg & 0x1f;
992 /* If weight is disabled, report weight source as 0 */
993 if (j == 1 && !(reg & 0x80))
994 data->pwm_weight_temp_sel[i] = 0;
995
996 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -0700997 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800998 data->weight_temp[j][i]
999 = nct6775_read_value(data,
1000 data->REG_WEIGHT_TEMP[j][i]);
1001 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001002 }
1003}
1004
1005static void nct6775_update_pwm_limits(struct device *dev)
1006{
1007 struct nct6775_data *data = dev_get_drvdata(dev);
1008 int i, j;
1009 u8 reg;
1010 u16 reg_t;
1011
1012 for (i = 0; i < data->pwm_num; i++) {
1013 if (!(data->has_pwm & (1 << i)))
1014 continue;
1015
Guenter Roeckc409fd42013-04-09 05:04:00 -07001016 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001017 data->fan_time[j][i] =
1018 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1019 }
1020
1021 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1022 /* Update only in matching mode or if never updated */
1023 if (!data->target_temp[i] ||
1024 data->pwm_enable[i] == thermal_cruise)
1025 data->target_temp[i] = reg_t & data->target_temp_mask;
1026 if (!data->target_speed[i] ||
1027 data->pwm_enable[i] == speed_cruise) {
1028 if (data->REG_TOLERANCE_H) {
1029 reg_t |= (nct6775_read_value(data,
1030 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1031 }
1032 data->target_speed[i] = reg_t;
1033 }
1034
1035 for (j = 0; j < data->auto_pwm_num; j++) {
1036 data->auto_pwm[i][j] =
1037 nct6775_read_value(data,
1038 NCT6775_AUTO_PWM(data, i, j));
1039 data->auto_temp[i][j] =
1040 nct6775_read_value(data,
1041 NCT6775_AUTO_TEMP(data, i, j));
1042 }
1043
1044 /* critical auto_pwm temperature data */
1045 data->auto_temp[i][data->auto_pwm_num] =
1046 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1047
1048 switch (data->kind) {
1049 case nct6775:
1050 reg = nct6775_read_value(data,
1051 NCT6775_REG_CRITICAL_ENAB[i]);
1052 data->auto_pwm[i][data->auto_pwm_num] =
1053 (reg & 0x02) ? 0xff : 0x00;
1054 break;
1055 case nct6776:
1056 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1057 break;
1058 case nct6779:
1059 reg = nct6775_read_value(data,
1060 NCT6779_REG_CRITICAL_PWM_ENABLE[i]);
1061 if (reg & 1)
1062 data->auto_pwm[i][data->auto_pwm_num] =
1063 nct6775_read_value(data,
1064 NCT6779_REG_CRITICAL_PWM[i]);
1065 else
1066 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1067 break;
1068 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001069 }
1070}
1071
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001072static struct nct6775_data *nct6775_update_device(struct device *dev)
1073{
1074 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001075 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001076
1077 mutex_lock(&data->update_lock);
1078
Guenter Roeck6445e662013-04-21 09:13:28 -07001079 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001080 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001081 /* Fan clock dividers */
1082 nct6775_update_fan_div_common(data);
1083
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001084 /* Measured voltages and limits */
1085 for (i = 0; i < data->in_num; i++) {
1086 if (!(data->have_in & (1 << i)))
1087 continue;
1088
1089 data->in[i][0] = nct6775_read_value(data,
1090 data->REG_VIN[i]);
1091 data->in[i][1] = nct6775_read_value(data,
1092 data->REG_IN_MINMAX[0][i]);
1093 data->in[i][2] = nct6775_read_value(data,
1094 data->REG_IN_MINMAX[1][i]);
1095 }
1096
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001097 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001098 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001099 u16 reg;
1100
1101 if (!(data->has_fan & (1 << i)))
1102 continue;
1103
1104 reg = nct6775_read_value(data, data->REG_FAN[i]);
1105 data->rpm[i] = data->fan_from_reg(reg,
1106 data->fan_div[i]);
1107
1108 if (data->has_fan_min & (1 << i))
1109 data->fan_min[i] = nct6775_read_value(data,
1110 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001111 data->fan_pulses[i] =
1112 nct6775_read_value(data, data->REG_FAN_PULSES[i]);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001113
1114 nct6775_select_fan_div(dev, data, i, reg);
1115 }
1116
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001117 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001118 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001119
Guenter Roeckaa136e52012-12-04 03:26:05 -08001120 /* Measured temperatures and limits */
1121 for (i = 0; i < NUM_TEMP; i++) {
1122 if (!(data->have_temp & (1 << i)))
1123 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001124 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001125 if (data->reg_temp[j][i])
1126 data->temp[j][i]
1127 = nct6775_read_temp(data,
1128 data->reg_temp[j][i]);
1129 }
1130 if (!(data->have_temp_fixed & (1 << i)))
1131 continue;
1132 data->temp_offset[i]
1133 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1134 }
1135
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001136 data->alarms = 0;
1137 for (i = 0; i < NUM_REG_ALARM; i++) {
1138 u8 alarm;
1139 if (!data->REG_ALARM[i])
1140 continue;
1141 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1142 data->alarms |= ((u64)alarm) << (i << 3);
1143 }
1144
1145 data->last_updated = jiffies;
1146 data->valid = true;
1147 }
1148
1149 mutex_unlock(&data->update_lock);
1150 return data;
1151}
1152
1153/*
1154 * Sysfs callback functions
1155 */
1156static ssize_t
1157show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1158{
1159 struct nct6775_data *data = nct6775_update_device(dev);
1160 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1161 int nr = sattr->nr;
1162 int index = sattr->index;
1163 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1164}
1165
1166static ssize_t
1167store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1168 size_t count)
1169{
1170 struct nct6775_data *data = dev_get_drvdata(dev);
1171 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1172 int nr = sattr->nr;
1173 int index = sattr->index;
1174 unsigned long val;
1175 int err = kstrtoul(buf, 10, &val);
1176 if (err < 0)
1177 return err;
1178 mutex_lock(&data->update_lock);
1179 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001180 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001181 data->in[nr][index]);
1182 mutex_unlock(&data->update_lock);
1183 return count;
1184}
1185
1186static ssize_t
1187show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1188{
1189 struct nct6775_data *data = nct6775_update_device(dev);
1190 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1191 int nr = data->ALARM_BITS[sattr->index];
1192 return sprintf(buf, "%u\n",
1193 (unsigned int)((data->alarms >> nr) & 0x01));
1194}
1195
1196static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
1197static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
1198static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
1199static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0);
1200static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0);
1201static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0);
1202static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0);
1203static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0);
1204static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0);
1205static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0);
1206static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0);
1207static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0);
1208static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0);
1209static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0);
1210static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0);
1211
1212static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
1213static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
1214static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
1215static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
1216static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
1217static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
1218static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
1219static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
1220static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
1221static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
1222static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
1223static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11);
1224static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12);
1225static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13);
1226static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14);
1227
1228static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg,
1229 store_in_reg, 0, 1);
1230static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg,
1231 store_in_reg, 1, 1);
1232static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg,
1233 store_in_reg, 2, 1);
1234static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg,
1235 store_in_reg, 3, 1);
1236static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg,
1237 store_in_reg, 4, 1);
1238static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg,
1239 store_in_reg, 5, 1);
1240static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg,
1241 store_in_reg, 6, 1);
1242static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg,
1243 store_in_reg, 7, 1);
1244static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg,
1245 store_in_reg, 8, 1);
1246static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg,
1247 store_in_reg, 9, 1);
1248static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg,
1249 store_in_reg, 10, 1);
1250static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg,
1251 store_in_reg, 11, 1);
1252static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg,
1253 store_in_reg, 12, 1);
1254static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg,
1255 store_in_reg, 13, 1);
1256static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg,
1257 store_in_reg, 14, 1);
1258
1259static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg,
1260 store_in_reg, 0, 2);
1261static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg,
1262 store_in_reg, 1, 2);
1263static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg,
1264 store_in_reg, 2, 2);
1265static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg,
1266 store_in_reg, 3, 2);
1267static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg,
1268 store_in_reg, 4, 2);
1269static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg,
1270 store_in_reg, 5, 2);
1271static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg,
1272 store_in_reg, 6, 2);
1273static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg,
1274 store_in_reg, 7, 2);
1275static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg,
1276 store_in_reg, 8, 2);
1277static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg,
1278 store_in_reg, 9, 2);
1279static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg,
1280 store_in_reg, 10, 2);
1281static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg,
1282 store_in_reg, 11, 2);
1283static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg,
1284 store_in_reg, 12, 2);
1285static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg,
1286 store_in_reg, 13, 2);
1287static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg,
1288 store_in_reg, 14, 2);
1289
1290static struct attribute *nct6775_attributes_in[15][5] = {
1291 {
1292 &sensor_dev_attr_in0_input.dev_attr.attr,
1293 &sensor_dev_attr_in0_min.dev_attr.attr,
1294 &sensor_dev_attr_in0_max.dev_attr.attr,
1295 &sensor_dev_attr_in0_alarm.dev_attr.attr,
1296 NULL
1297 },
1298 {
1299 &sensor_dev_attr_in1_input.dev_attr.attr,
1300 &sensor_dev_attr_in1_min.dev_attr.attr,
1301 &sensor_dev_attr_in1_max.dev_attr.attr,
1302 &sensor_dev_attr_in1_alarm.dev_attr.attr,
1303 NULL
1304 },
1305 {
1306 &sensor_dev_attr_in2_input.dev_attr.attr,
1307 &sensor_dev_attr_in2_min.dev_attr.attr,
1308 &sensor_dev_attr_in2_max.dev_attr.attr,
1309 &sensor_dev_attr_in2_alarm.dev_attr.attr,
1310 NULL
1311 },
1312 {
1313 &sensor_dev_attr_in3_input.dev_attr.attr,
1314 &sensor_dev_attr_in3_min.dev_attr.attr,
1315 &sensor_dev_attr_in3_max.dev_attr.attr,
1316 &sensor_dev_attr_in3_alarm.dev_attr.attr,
1317 NULL
1318 },
1319 {
1320 &sensor_dev_attr_in4_input.dev_attr.attr,
1321 &sensor_dev_attr_in4_min.dev_attr.attr,
1322 &sensor_dev_attr_in4_max.dev_attr.attr,
1323 &sensor_dev_attr_in4_alarm.dev_attr.attr,
1324 NULL
1325 },
1326 {
1327 &sensor_dev_attr_in5_input.dev_attr.attr,
1328 &sensor_dev_attr_in5_min.dev_attr.attr,
1329 &sensor_dev_attr_in5_max.dev_attr.attr,
1330 &sensor_dev_attr_in5_alarm.dev_attr.attr,
1331 NULL
1332 },
1333 {
1334 &sensor_dev_attr_in6_input.dev_attr.attr,
1335 &sensor_dev_attr_in6_min.dev_attr.attr,
1336 &sensor_dev_attr_in6_max.dev_attr.attr,
1337 &sensor_dev_attr_in6_alarm.dev_attr.attr,
1338 NULL
1339 },
1340 {
1341 &sensor_dev_attr_in7_input.dev_attr.attr,
1342 &sensor_dev_attr_in7_min.dev_attr.attr,
1343 &sensor_dev_attr_in7_max.dev_attr.attr,
1344 &sensor_dev_attr_in7_alarm.dev_attr.attr,
1345 NULL
1346 },
1347 {
1348 &sensor_dev_attr_in8_input.dev_attr.attr,
1349 &sensor_dev_attr_in8_min.dev_attr.attr,
1350 &sensor_dev_attr_in8_max.dev_attr.attr,
1351 &sensor_dev_attr_in8_alarm.dev_attr.attr,
1352 NULL
1353 },
1354 {
1355 &sensor_dev_attr_in9_input.dev_attr.attr,
1356 &sensor_dev_attr_in9_min.dev_attr.attr,
1357 &sensor_dev_attr_in9_max.dev_attr.attr,
1358 &sensor_dev_attr_in9_alarm.dev_attr.attr,
1359 NULL
1360 },
1361 {
1362 &sensor_dev_attr_in10_input.dev_attr.attr,
1363 &sensor_dev_attr_in10_min.dev_attr.attr,
1364 &sensor_dev_attr_in10_max.dev_attr.attr,
1365 &sensor_dev_attr_in10_alarm.dev_attr.attr,
1366 NULL
1367 },
1368 {
1369 &sensor_dev_attr_in11_input.dev_attr.attr,
1370 &sensor_dev_attr_in11_min.dev_attr.attr,
1371 &sensor_dev_attr_in11_max.dev_attr.attr,
1372 &sensor_dev_attr_in11_alarm.dev_attr.attr,
1373 NULL
1374 },
1375 {
1376 &sensor_dev_attr_in12_input.dev_attr.attr,
1377 &sensor_dev_attr_in12_min.dev_attr.attr,
1378 &sensor_dev_attr_in12_max.dev_attr.attr,
1379 &sensor_dev_attr_in12_alarm.dev_attr.attr,
1380 NULL
1381 },
1382 {
1383 &sensor_dev_attr_in13_input.dev_attr.attr,
1384 &sensor_dev_attr_in13_min.dev_attr.attr,
1385 &sensor_dev_attr_in13_max.dev_attr.attr,
1386 &sensor_dev_attr_in13_alarm.dev_attr.attr,
1387 NULL
1388 },
1389 {
1390 &sensor_dev_attr_in14_input.dev_attr.attr,
1391 &sensor_dev_attr_in14_min.dev_attr.attr,
1392 &sensor_dev_attr_in14_max.dev_attr.attr,
1393 &sensor_dev_attr_in14_alarm.dev_attr.attr,
1394 NULL
1395 },
1396};
1397
1398static const struct attribute_group nct6775_group_in[15] = {
1399 { .attrs = nct6775_attributes_in[0] },
1400 { .attrs = nct6775_attributes_in[1] },
1401 { .attrs = nct6775_attributes_in[2] },
1402 { .attrs = nct6775_attributes_in[3] },
1403 { .attrs = nct6775_attributes_in[4] },
1404 { .attrs = nct6775_attributes_in[5] },
1405 { .attrs = nct6775_attributes_in[6] },
1406 { .attrs = nct6775_attributes_in[7] },
1407 { .attrs = nct6775_attributes_in[8] },
1408 { .attrs = nct6775_attributes_in[9] },
1409 { .attrs = nct6775_attributes_in[10] },
1410 { .attrs = nct6775_attributes_in[11] },
1411 { .attrs = nct6775_attributes_in[12] },
1412 { .attrs = nct6775_attributes_in[13] },
1413 { .attrs = nct6775_attributes_in[14] },
1414};
1415
1416static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001417show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1418{
1419 struct nct6775_data *data = nct6775_update_device(dev);
1420 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1421 int nr = sattr->index;
1422 return sprintf(buf, "%d\n", data->rpm[nr]);
1423}
1424
1425static ssize_t
1426show_fan_min(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 = sattr->index;
1431 return sprintf(buf, "%d\n",
1432 data->fan_from_reg_min(data->fan_min[nr],
1433 data->fan_div[nr]));
1434}
1435
1436static ssize_t
1437show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1438{
1439 struct nct6775_data *data = nct6775_update_device(dev);
1440 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1441 int nr = sattr->index;
1442 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1443}
1444
1445static ssize_t
1446store_fan_min(struct device *dev, struct device_attribute *attr,
1447 const char *buf, size_t count)
1448{
1449 struct nct6775_data *data = dev_get_drvdata(dev);
1450 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1451 int nr = sattr->index;
1452 unsigned long val;
1453 int err;
1454 unsigned int reg;
1455 u8 new_div;
1456
1457 err = kstrtoul(buf, 10, &val);
1458 if (err < 0)
1459 return err;
1460
1461 mutex_lock(&data->update_lock);
1462 if (!data->has_fan_div) {
1463 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1464 if (!val) {
1465 val = 0xff1f;
1466 } else {
1467 if (val > 1350000U)
1468 val = 135000U;
1469 val = 1350000U / val;
1470 val = (val & 0x1f) | ((val << 3) & 0xff00);
1471 }
1472 data->fan_min[nr] = val;
1473 goto write_min; /* Leave fan divider alone */
1474 }
1475 if (!val) {
1476 /* No min limit, alarm disabled */
1477 data->fan_min[nr] = 255;
1478 new_div = data->fan_div[nr]; /* No change */
1479 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1480 goto write_div;
1481 }
1482 reg = 1350000U / val;
1483 if (reg >= 128 * 255) {
1484 /*
1485 * Speed below this value cannot possibly be represented,
1486 * even with the highest divider (128)
1487 */
1488 data->fan_min[nr] = 254;
1489 new_div = 7; /* 128 == (1 << 7) */
1490 dev_warn(dev,
1491 "fan%u low limit %lu below minimum %u, set to minimum\n",
1492 nr + 1, val, data->fan_from_reg_min(254, 7));
1493 } else if (!reg) {
1494 /*
1495 * Speed above this value cannot possibly be represented,
1496 * even with the lowest divider (1)
1497 */
1498 data->fan_min[nr] = 1;
1499 new_div = 0; /* 1 == (1 << 0) */
1500 dev_warn(dev,
1501 "fan%u low limit %lu above maximum %u, set to maximum\n",
1502 nr + 1, val, data->fan_from_reg_min(1, 0));
1503 } else {
1504 /*
1505 * Automatically pick the best divider, i.e. the one such
1506 * that the min limit will correspond to a register value
1507 * in the 96..192 range
1508 */
1509 new_div = 0;
1510 while (reg > 192 && new_div < 7) {
1511 reg >>= 1;
1512 new_div++;
1513 }
1514 data->fan_min[nr] = reg;
1515 }
1516
1517write_div:
1518 /*
1519 * Write both the fan clock divider (if it changed) and the new
1520 * fan min (unconditionally)
1521 */
1522 if (new_div != data->fan_div[nr]) {
1523 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1524 nr + 1, div_from_reg(data->fan_div[nr]),
1525 div_from_reg(new_div));
1526 data->fan_div[nr] = new_div;
1527 nct6775_write_fan_div_common(data, nr);
1528 /* Give the chip time to sample a new speed value */
1529 data->last_updated = jiffies;
1530 }
1531
1532write_min:
1533 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1534 mutex_unlock(&data->update_lock);
1535
1536 return count;
1537}
1538
Guenter Roeck5c25d952012-12-11 07:29:06 -08001539static ssize_t
1540show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1541{
1542 struct nct6775_data *data = nct6775_update_device(dev);
1543 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1544 int p = data->fan_pulses[sattr->index];
1545
1546 return sprintf(buf, "%d\n", p ? : 4);
1547}
1548
1549static ssize_t
1550store_fan_pulses(struct device *dev, struct device_attribute *attr,
1551 const char *buf, size_t count)
1552{
1553 struct nct6775_data *data = dev_get_drvdata(dev);
1554 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1555 int nr = sattr->index;
1556 unsigned long val;
1557 int err;
1558
1559 err = kstrtoul(buf, 10, &val);
1560 if (err < 0)
1561 return err;
1562
1563 if (val > 4)
1564 return -EINVAL;
1565
1566 mutex_lock(&data->update_lock);
1567 data->fan_pulses[nr] = val & 3;
1568 nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3);
1569 mutex_unlock(&data->update_lock);
1570
1571 return count;
1572}
1573
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001574static struct sensor_device_attribute sda_fan_input[] = {
1575 SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
1576 SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
1577 SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
1578 SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
1579 SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
1580};
1581
1582static struct sensor_device_attribute sda_fan_alarm[] = {
1583 SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE),
1584 SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1),
1585 SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2),
1586 SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3),
1587 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4),
1588};
1589
1590static struct sensor_device_attribute sda_fan_min[] = {
1591 SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
1592 store_fan_min, 0),
1593 SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
1594 store_fan_min, 1),
1595 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
1596 store_fan_min, 2),
1597 SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
1598 store_fan_min, 3),
1599 SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
1600 store_fan_min, 4),
1601};
1602
Guenter Roeck5c25d952012-12-11 07:29:06 -08001603static struct sensor_device_attribute sda_fan_pulses[] = {
1604 SENSOR_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1605 store_fan_pulses, 0),
1606 SENSOR_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1607 store_fan_pulses, 1),
1608 SENSOR_ATTR(fan3_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1609 store_fan_pulses, 2),
1610 SENSOR_ATTR(fan4_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1611 store_fan_pulses, 3),
1612 SENSOR_ATTR(fan5_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1613 store_fan_pulses, 4),
1614};
1615
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001616static struct sensor_device_attribute sda_fan_div[] = {
1617 SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
1618 SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
1619 SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
1620 SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
1621 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
1622};
1623
1624static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001625show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1626{
1627 struct nct6775_data *data = nct6775_update_device(dev);
1628 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1629 int nr = sattr->index;
1630 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1631}
1632
1633static ssize_t
1634show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1635{
1636 struct nct6775_data *data = nct6775_update_device(dev);
1637 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1638 int nr = sattr->nr;
1639 int index = sattr->index;
1640
1641 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1642}
1643
1644static ssize_t
1645store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1646 size_t count)
1647{
1648 struct nct6775_data *data = dev_get_drvdata(dev);
1649 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1650 int nr = sattr->nr;
1651 int index = sattr->index;
1652 int err;
1653 long val;
1654
1655 err = kstrtol(buf, 10, &val);
1656 if (err < 0)
1657 return err;
1658
1659 mutex_lock(&data->update_lock);
1660 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1661 nct6775_write_temp(data, data->reg_temp[index][nr],
1662 data->temp[index][nr]);
1663 mutex_unlock(&data->update_lock);
1664 return count;
1665}
1666
1667static ssize_t
1668show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1669{
1670 struct nct6775_data *data = nct6775_update_device(dev);
1671 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1672
1673 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1674}
1675
1676static ssize_t
1677store_temp_offset(struct device *dev, struct device_attribute *attr,
1678 const char *buf, size_t count)
1679{
1680 struct nct6775_data *data = dev_get_drvdata(dev);
1681 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1682 int nr = sattr->index;
1683 long val;
1684 int err;
1685
1686 err = kstrtol(buf, 10, &val);
1687 if (err < 0)
1688 return err;
1689
1690 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1691
1692 mutex_lock(&data->update_lock);
1693 data->temp_offset[nr] = val;
1694 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1695 mutex_unlock(&data->update_lock);
1696
1697 return count;
1698}
1699
1700static ssize_t
1701show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1702{
1703 struct nct6775_data *data = nct6775_update_device(dev);
1704 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1705 int nr = sattr->index;
1706 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
1707}
1708
1709static ssize_t
1710store_temp_type(struct device *dev, struct device_attribute *attr,
1711 const char *buf, size_t count)
1712{
1713 struct nct6775_data *data = nct6775_update_device(dev);
1714 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1715 int nr = sattr->index;
1716 unsigned long val;
1717 int err;
1718 u8 vbat, diode, bit;
1719
1720 err = kstrtoul(buf, 10, &val);
1721 if (err < 0)
1722 return err;
1723
1724 if (val != 1 && val != 3 && val != 4)
1725 return -EINVAL;
1726
1727 mutex_lock(&data->update_lock);
1728
1729 data->temp_type[nr] = val;
1730 vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr);
1731 diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr);
1732 bit = 0x02 << nr;
1733 switch (val) {
1734 case 1: /* CPU diode (diode, current mode) */
1735 vbat |= bit;
1736 diode |= bit;
1737 break;
1738 case 3: /* diode, voltage mode */
1739 vbat |= bit;
1740 break;
1741 case 4: /* thermistor */
1742 break;
1743 }
1744 nct6775_write_value(data, data->REG_VBAT, vbat);
1745 nct6775_write_value(data, data->REG_DIODE, diode);
1746
1747 mutex_unlock(&data->update_lock);
1748 return count;
1749}
1750
1751static struct sensor_device_attribute_2 sda_temp_input[] = {
1752 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
1753 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0),
1754 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0),
1755 SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0),
1756 SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0),
1757 SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0),
1758 SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0),
1759 SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0),
1760 SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0),
1761 SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0),
1762};
1763
1764static struct sensor_device_attribute sda_temp_label[] = {
1765 SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
1766 SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
1767 SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
1768 SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
1769 SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
1770 SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
1771 SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
1772 SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
1773 SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
1774 SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9),
1775};
1776
1777static struct sensor_device_attribute_2 sda_temp_max[] = {
1778 SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1779 0, 1),
1780 SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1781 1, 1),
1782 SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1783 2, 1),
1784 SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1785 3, 1),
1786 SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1787 4, 1),
1788 SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1789 5, 1),
1790 SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1791 6, 1),
1792 SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1793 7, 1),
1794 SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1795 8, 1),
1796 SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1797 9, 1),
1798};
1799
1800static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
1801 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1802 0, 2),
1803 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1804 1, 2),
1805 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1806 2, 2),
1807 SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1808 3, 2),
1809 SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1810 4, 2),
1811 SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1812 5, 2),
1813 SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1814 6, 2),
1815 SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1816 7, 2),
1817 SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1818 8, 2),
1819 SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1820 9, 2),
1821};
1822
1823static struct sensor_device_attribute_2 sda_temp_crit[] = {
1824 SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1825 0, 3),
1826 SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1827 1, 3),
1828 SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1829 2, 3),
1830 SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1831 3, 3),
1832 SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1833 4, 3),
1834 SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1835 5, 3),
1836 SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1837 6, 3),
1838 SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1839 7, 3),
1840 SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1841 8, 3),
1842 SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1843 9, 3),
1844};
1845
1846static struct sensor_device_attribute sda_temp_offset[] = {
1847 SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1848 store_temp_offset, 0),
1849 SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1850 store_temp_offset, 1),
1851 SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1852 store_temp_offset, 2),
1853 SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1854 store_temp_offset, 3),
1855 SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1856 store_temp_offset, 4),
1857 SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1858 store_temp_offset, 5),
1859};
1860
1861static struct sensor_device_attribute sda_temp_type[] = {
1862 SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
1863 store_temp_type, 0),
1864 SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
1865 store_temp_type, 1),
1866 SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
1867 store_temp_type, 2),
1868 SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type,
1869 store_temp_type, 3),
1870 SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type,
1871 store_temp_type, 4),
1872 SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type,
1873 store_temp_type, 5),
1874};
1875
1876static struct sensor_device_attribute sda_temp_alarm[] = {
1877 SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
1878 TEMP_ALARM_BASE),
1879 SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
1880 TEMP_ALARM_BASE + 1),
1881 SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
1882 TEMP_ALARM_BASE + 2),
1883 SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
1884 TEMP_ALARM_BASE + 3),
1885 SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
1886 TEMP_ALARM_BASE + 4),
1887 SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
1888 TEMP_ALARM_BASE + 5),
1889};
1890
1891#define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm)
1892
1893static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001894show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
1895{
1896 struct nct6775_data *data = nct6775_update_device(dev);
1897 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1898
1899 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
1900}
1901
1902static ssize_t
1903store_pwm_mode(struct device *dev, struct device_attribute *attr,
1904 const char *buf, size_t count)
1905{
1906 struct nct6775_data *data = dev_get_drvdata(dev);
1907 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1908 int nr = sattr->index;
1909 unsigned long val;
1910 int err;
1911 u8 reg;
1912
1913 err = kstrtoul(buf, 10, &val);
1914 if (err < 0)
1915 return err;
1916
1917 if (val > 1)
1918 return -EINVAL;
1919
1920 /* Setting DC mode is not supported for all chips/channels */
1921 if (data->REG_PWM_MODE[nr] == 0) {
1922 if (val)
1923 return -EINVAL;
1924 return count;
1925 }
1926
1927 mutex_lock(&data->update_lock);
1928 data->pwm_mode[nr] = val;
1929 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
1930 reg &= ~data->PWM_MODE_MASK[nr];
1931 if (val)
1932 reg |= data->PWM_MODE_MASK[nr];
1933 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
1934 mutex_unlock(&data->update_lock);
1935 return count;
1936}
1937
1938static ssize_t
1939show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
1940{
1941 struct nct6775_data *data = nct6775_update_device(dev);
1942 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1943 int nr = sattr->nr;
1944 int index = sattr->index;
1945 int pwm;
1946
1947 /*
1948 * For automatic fan control modes, show current pwm readings.
1949 * Otherwise, show the configured value.
1950 */
1951 if (index == 0 && data->pwm_enable[nr] > manual)
1952 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
1953 else
1954 pwm = data->pwm[index][nr];
1955
1956 return sprintf(buf, "%d\n", pwm);
1957}
1958
1959static ssize_t
1960store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
1961 size_t count)
1962{
1963 struct nct6775_data *data = dev_get_drvdata(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 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001968 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
1969 int maxval[7]
1970 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001971 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001972 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001973
1974 err = kstrtoul(buf, 10, &val);
1975 if (err < 0)
1976 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001977 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001978
1979 mutex_lock(&data->update_lock);
1980 data->pwm[index][nr] = val;
1981 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001982 if (index == 2) { /* floor: disable if val == 0 */
1983 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
1984 reg &= 0x7f;
1985 if (val)
1986 reg |= 0x80;
1987 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
1988 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001989 mutex_unlock(&data->update_lock);
1990 return count;
1991}
1992
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001993/* Returns 0 if OK, -EINVAL otherwise */
1994static int check_trip_points(struct nct6775_data *data, int nr)
1995{
1996 int i;
1997
1998 for (i = 0; i < data->auto_pwm_num - 1; i++) {
1999 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2000 return -EINVAL;
2001 }
2002 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2003 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2004 return -EINVAL;
2005 }
2006 /* validate critical temperature and pwm if enabled (pwm > 0) */
2007 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2008 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2009 data->auto_temp[nr][data->auto_pwm_num] ||
2010 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2011 data->auto_pwm[nr][data->auto_pwm_num])
2012 return -EINVAL;
2013 }
2014 return 0;
2015}
2016
2017static void pwm_update_registers(struct nct6775_data *data, int nr)
2018{
2019 u8 reg;
2020
2021 switch (data->pwm_enable[nr]) {
2022 case off:
2023 case manual:
2024 break;
2025 case speed_cruise:
2026 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2027 reg = (reg & ~data->tolerance_mask) |
2028 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2029 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2030 nct6775_write_value(data, data->REG_TARGET[nr],
2031 data->target_speed[nr] & 0xff);
2032 if (data->REG_TOLERANCE_H) {
2033 reg = (data->target_speed[nr] >> 8) & 0x0f;
2034 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2035 nct6775_write_value(data,
2036 data->REG_TOLERANCE_H[nr],
2037 reg);
2038 }
2039 break;
2040 case thermal_cruise:
2041 nct6775_write_value(data, data->REG_TARGET[nr],
2042 data->target_temp[nr]);
2043 /* intentional */
2044 default:
2045 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2046 reg = (reg & ~data->tolerance_mask) |
2047 data->temp_tolerance[0][nr];
2048 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2049 break;
2050 }
2051}
2052
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002053static ssize_t
2054show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2055{
2056 struct nct6775_data *data = nct6775_update_device(dev);
2057 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2058
2059 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2060}
2061
2062static ssize_t
2063store_pwm_enable(struct device *dev, struct device_attribute *attr,
2064 const char *buf, size_t count)
2065{
2066 struct nct6775_data *data = dev_get_drvdata(dev);
2067 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2068 int nr = sattr->index;
2069 unsigned long val;
2070 int err;
2071 u16 reg;
2072
2073 err = kstrtoul(buf, 10, &val);
2074 if (err < 0)
2075 return err;
2076
2077 if (val > sf4)
2078 return -EINVAL;
2079
2080 if (val == sf3 && data->kind != nct6775)
2081 return -EINVAL;
2082
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002083 if (val == sf4 && check_trip_points(data, nr)) {
2084 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2085 dev_err(dev, "Adjust trip points and try again\n");
2086 return -EINVAL;
2087 }
2088
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002089 mutex_lock(&data->update_lock);
2090 data->pwm_enable[nr] = val;
2091 if (val == off) {
2092 /*
2093 * turn off pwm control: select manual mode, set pwm to maximum
2094 */
2095 data->pwm[0][nr] = 255;
2096 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2097 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002098 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002099 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2100 reg &= 0x0f;
2101 reg |= pwm_enable_to_reg(val) << 4;
2102 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2103 mutex_unlock(&data->update_lock);
2104 return count;
2105}
2106
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002107static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002108show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002109{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002110 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002111
2112 for (i = 0; i < NUM_TEMP; i++) {
2113 if (!(data->have_temp & (1 << i)))
2114 continue;
2115 if (src == data->temp_src[i]) {
2116 sel = i + 1;
2117 break;
2118 }
2119 }
2120
2121 return sprintf(buf, "%d\n", sel);
2122}
2123
2124static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002125show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2126{
2127 struct nct6775_data *data = nct6775_update_device(dev);
2128 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2129 int index = sattr->index;
2130
2131 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2132}
2133
2134static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002135store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2136 const char *buf, size_t count)
2137{
2138 struct nct6775_data *data = nct6775_update_device(dev);
2139 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2140 int nr = sattr->index;
2141 unsigned long val;
2142 int err, reg, src;
2143
2144 err = kstrtoul(buf, 10, &val);
2145 if (err < 0)
2146 return err;
2147 if (val == 0 || val > NUM_TEMP)
2148 return -EINVAL;
2149 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2150 return -EINVAL;
2151
2152 mutex_lock(&data->update_lock);
2153 src = data->temp_src[val - 1];
2154 data->pwm_temp_sel[nr] = src;
2155 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2156 reg &= 0xe0;
2157 reg |= src;
2158 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2159 mutex_unlock(&data->update_lock);
2160
2161 return count;
2162}
2163
2164static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002165show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2166 char *buf)
2167{
2168 struct nct6775_data *data = nct6775_update_device(dev);
2169 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2170 int index = sattr->index;
2171
2172 return show_pwm_temp_sel_common(data, buf,
2173 data->pwm_weight_temp_sel[index]);
2174}
2175
2176static ssize_t
2177store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2178 const char *buf, size_t count)
2179{
2180 struct nct6775_data *data = nct6775_update_device(dev);
2181 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2182 int nr = sattr->index;
2183 unsigned long val;
2184 int err, reg, src;
2185
2186 err = kstrtoul(buf, 10, &val);
2187 if (err < 0)
2188 return err;
2189 if (val > NUM_TEMP)
2190 return -EINVAL;
2191 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2192 !data->temp_src[val - 1]))
2193 return -EINVAL;
2194
2195 mutex_lock(&data->update_lock);
2196 if (val) {
2197 src = data->temp_src[val - 1];
2198 data->pwm_weight_temp_sel[nr] = src;
2199 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2200 reg &= 0xe0;
2201 reg |= (src | 0x80);
2202 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2203 } else {
2204 data->pwm_weight_temp_sel[nr] = 0;
2205 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2206 reg &= 0x7f;
2207 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2208 }
2209 mutex_unlock(&data->update_lock);
2210
2211 return count;
2212}
2213
2214static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002215show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2216{
2217 struct nct6775_data *data = nct6775_update_device(dev);
2218 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2219
2220 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2221}
2222
2223static ssize_t
2224store_target_temp(struct device *dev, struct device_attribute *attr,
2225 const char *buf, size_t count)
2226{
2227 struct nct6775_data *data = dev_get_drvdata(dev);
2228 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2229 int nr = sattr->index;
2230 unsigned long val;
2231 int err;
2232
2233 err = kstrtoul(buf, 10, &val);
2234 if (err < 0)
2235 return err;
2236
2237 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2238 data->target_temp_mask);
2239
2240 mutex_lock(&data->update_lock);
2241 data->target_temp[nr] = val;
2242 pwm_update_registers(data, nr);
2243 mutex_unlock(&data->update_lock);
2244 return count;
2245}
2246
2247static ssize_t
2248show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2249{
2250 struct nct6775_data *data = nct6775_update_device(dev);
2251 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2252 int nr = sattr->index;
2253
2254 return sprintf(buf, "%d\n",
2255 fan_from_reg16(data->target_speed[nr],
2256 data->fan_div[nr]));
2257}
2258
2259static ssize_t
2260store_target_speed(struct device *dev, struct device_attribute *attr,
2261 const char *buf, size_t count)
2262{
2263 struct nct6775_data *data = dev_get_drvdata(dev);
2264 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2265 int nr = sattr->index;
2266 unsigned long val;
2267 int err;
2268 u16 speed;
2269
2270 err = kstrtoul(buf, 10, &val);
2271 if (err < 0)
2272 return err;
2273
2274 val = clamp_val(val, 0, 1350000U);
2275 speed = fan_to_reg(val, data->fan_div[nr]);
2276
2277 mutex_lock(&data->update_lock);
2278 data->target_speed[nr] = speed;
2279 pwm_update_registers(data, nr);
2280 mutex_unlock(&data->update_lock);
2281 return count;
2282}
2283
2284static ssize_t
2285show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2286 char *buf)
2287{
2288 struct nct6775_data *data = nct6775_update_device(dev);
2289 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2290 int nr = sattr->nr;
2291 int index = sattr->index;
2292
2293 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2294}
2295
2296static ssize_t
2297store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2298 const char *buf, size_t count)
2299{
2300 struct nct6775_data *data = dev_get_drvdata(dev);
2301 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2302 int nr = sattr->nr;
2303 int index = sattr->index;
2304 unsigned long val;
2305 int err;
2306
2307 err = kstrtoul(buf, 10, &val);
2308 if (err < 0)
2309 return err;
2310
2311 /* Limit tolerance as needed */
2312 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2313
2314 mutex_lock(&data->update_lock);
2315 data->temp_tolerance[index][nr] = val;
2316 if (index)
2317 pwm_update_registers(data, nr);
2318 else
2319 nct6775_write_value(data,
2320 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2321 val);
2322 mutex_unlock(&data->update_lock);
2323 return count;
2324}
2325
2326/*
2327 * Fan speed tolerance is a tricky beast, since the associated register is
2328 * a tick counter, but the value is reported and configured as rpm.
2329 * Compute resulting low and high rpm values and report the difference.
2330 */
2331static ssize_t
2332show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2333 char *buf)
2334{
2335 struct nct6775_data *data = nct6775_update_device(dev);
2336 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2337 int nr = sattr->index;
2338 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2339 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2340 int tolerance;
2341
2342 if (low <= 0)
2343 low = 1;
2344 if (high > 0xffff)
2345 high = 0xffff;
2346 if (high < low)
2347 high = low;
2348
2349 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2350 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2351
2352 return sprintf(buf, "%d\n", tolerance);
2353}
2354
2355static ssize_t
2356store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2357 const char *buf, size_t count)
2358{
2359 struct nct6775_data *data = dev_get_drvdata(dev);
2360 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2361 int nr = sattr->index;
2362 unsigned long val;
2363 int err;
2364 int low, high;
2365
2366 err = kstrtoul(buf, 10, &val);
2367 if (err < 0)
2368 return err;
2369
2370 high = fan_from_reg16(data->target_speed[nr],
2371 data->fan_div[nr]) + val;
2372 low = fan_from_reg16(data->target_speed[nr],
2373 data->fan_div[nr]) - val;
2374 if (low <= 0)
2375 low = 1;
2376 if (high < low)
2377 high = low;
2378
2379 val = (fan_to_reg(low, data->fan_div[nr]) -
2380 fan_to_reg(high, data->fan_div[nr])) / 2;
2381
2382 /* Limit tolerance as needed */
2383 val = clamp_val(val, 0, data->speed_tolerance_limit);
2384
2385 mutex_lock(&data->update_lock);
2386 data->target_speed_tolerance[nr] = val;
2387 pwm_update_registers(data, nr);
2388 mutex_unlock(&data->update_lock);
2389 return count;
2390}
2391
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002392static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2393static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0);
2394static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0);
2395static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0);
2396static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0);
2397
2398static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2399 store_pwm_mode, 0);
2400static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2401 store_pwm_mode, 1);
2402static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2403 store_pwm_mode, 2);
2404static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2405 store_pwm_mode, 3);
2406static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2407 store_pwm_mode, 4);
2408
2409static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2410 store_pwm_enable, 0);
2411static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2412 store_pwm_enable, 1);
2413static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2414 store_pwm_enable, 2);
2415static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2416 store_pwm_enable, 3);
2417static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2418 store_pwm_enable, 4);
2419
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002420static SENSOR_DEVICE_ATTR(pwm1_temp_sel, S_IWUSR | S_IRUGO,
2421 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2422static SENSOR_DEVICE_ATTR(pwm2_temp_sel, S_IWUSR | S_IRUGO,
2423 show_pwm_temp_sel, store_pwm_temp_sel, 1);
2424static SENSOR_DEVICE_ATTR(pwm3_temp_sel, S_IWUSR | S_IRUGO,
2425 show_pwm_temp_sel, store_pwm_temp_sel, 2);
2426static SENSOR_DEVICE_ATTR(pwm4_temp_sel, S_IWUSR | S_IRUGO,
2427 show_pwm_temp_sel, store_pwm_temp_sel, 3);
2428static SENSOR_DEVICE_ATTR(pwm5_temp_sel, S_IWUSR | S_IRUGO,
2429 show_pwm_temp_sel, store_pwm_temp_sel, 4);
2430
2431static SENSOR_DEVICE_ATTR(pwm1_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2432 store_target_temp, 0);
2433static SENSOR_DEVICE_ATTR(pwm2_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2434 store_target_temp, 1);
2435static SENSOR_DEVICE_ATTR(pwm3_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2436 store_target_temp, 2);
2437static SENSOR_DEVICE_ATTR(pwm4_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2438 store_target_temp, 3);
2439static SENSOR_DEVICE_ATTR(pwm5_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2440 store_target_temp, 4);
2441
2442static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_target_speed,
2443 store_target_speed, 0);
2444static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_target_speed,
2445 store_target_speed, 1);
2446static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_target_speed,
2447 store_target_speed, 2);
2448static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_target_speed,
2449 store_target_speed, 3);
2450static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_target_speed,
2451 store_target_speed, 4);
2452
2453static SENSOR_DEVICE_ATTR(fan1_tolerance, S_IWUSR | S_IRUGO,
2454 show_speed_tolerance, store_speed_tolerance, 0);
2455static SENSOR_DEVICE_ATTR(fan2_tolerance, S_IWUSR | S_IRUGO,
2456 show_speed_tolerance, store_speed_tolerance, 1);
2457static SENSOR_DEVICE_ATTR(fan3_tolerance, S_IWUSR | S_IRUGO,
2458 show_speed_tolerance, store_speed_tolerance, 2);
2459static SENSOR_DEVICE_ATTR(fan4_tolerance, S_IWUSR | S_IRUGO,
2460 show_speed_tolerance, store_speed_tolerance, 3);
2461static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO,
2462 show_speed_tolerance, store_speed_tolerance, 4);
2463
2464/* Smart Fan registers */
2465
2466static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002467show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2468{
2469 struct nct6775_data *data = nct6775_update_device(dev);
2470 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2471 int nr = sattr->nr;
2472 int index = sattr->index;
2473
2474 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2475}
2476
2477static ssize_t
2478store_weight_temp(struct device *dev, struct device_attribute *attr,
2479 const char *buf, size_t count)
2480{
2481 struct nct6775_data *data = dev_get_drvdata(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 unsigned long val;
2486 int err;
2487
2488 err = kstrtoul(buf, 10, &val);
2489 if (err < 0)
2490 return err;
2491
2492 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2493
2494 mutex_lock(&data->update_lock);
2495 data->weight_temp[index][nr] = val;
2496 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2497 mutex_unlock(&data->update_lock);
2498 return count;
2499}
2500
2501static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO,
2502 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2503 0);
2504static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO,
2505 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2506 1);
2507static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO,
2508 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2509 2);
2510static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO,
2511 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2512 3);
2513static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO,
2514 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2515 4);
2516
2517static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO,
2518 show_weight_temp, store_weight_temp, 0, 0);
2519static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO,
2520 show_weight_temp, store_weight_temp, 1, 0);
2521static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO,
2522 show_weight_temp, store_weight_temp, 2, 0);
2523static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO,
2524 show_weight_temp, store_weight_temp, 3, 0);
2525static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO,
2526 show_weight_temp, store_weight_temp, 4, 0);
2527
2528static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2529 show_weight_temp, store_weight_temp, 0, 1);
2530static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2531 show_weight_temp, store_weight_temp, 1, 1);
2532static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2533 show_weight_temp, store_weight_temp, 2, 1);
2534static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2535 show_weight_temp, store_weight_temp, 3, 1);
2536static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2537 show_weight_temp, store_weight_temp, 4, 1);
2538
2539static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO,
2540 show_weight_temp, store_weight_temp, 0, 2);
2541static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO,
2542 show_weight_temp, store_weight_temp, 1, 2);
2543static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO,
2544 show_weight_temp, store_weight_temp, 2, 2);
2545static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO,
2546 show_weight_temp, store_weight_temp, 3, 2);
2547static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO,
2548 show_weight_temp, store_weight_temp, 4, 2);
2549
2550static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO,
2551 show_pwm, store_pwm, 0, 5);
2552static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO,
2553 show_pwm, store_pwm, 1, 5);
2554static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO,
2555 show_pwm, store_pwm, 2, 5);
2556static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO,
2557 show_pwm, store_pwm, 3, 5);
2558static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO,
2559 show_pwm, store_pwm, 4, 5);
2560
2561/* duty_base is not supported on all chips */
2562static struct sensor_device_attribute_2 sda_weight_duty_base[] = {
2563 SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO,
2564 show_pwm, store_pwm, 0, 6),
2565 SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO,
2566 show_pwm, store_pwm, 1, 6),
2567 SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO,
2568 show_pwm, store_pwm, 2, 6),
2569 SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO,
2570 show_pwm, store_pwm, 3, 6),
2571 SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO,
2572 show_pwm, store_pwm, 4, 6),
2573};
2574
2575static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002576show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2577{
2578 struct nct6775_data *data = nct6775_update_device(dev);
2579 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2580 int nr = sattr->nr;
2581 int index = sattr->index;
2582
2583 return sprintf(buf, "%d\n",
2584 step_time_from_reg(data->fan_time[index][nr],
2585 data->pwm_mode[nr]));
2586}
2587
2588static ssize_t
2589store_fan_time(struct device *dev, struct device_attribute *attr,
2590 const char *buf, size_t count)
2591{
2592 struct nct6775_data *data = dev_get_drvdata(dev);
2593 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2594 int nr = sattr->nr;
2595 int index = sattr->index;
2596 unsigned long val;
2597 int err;
2598
2599 err = kstrtoul(buf, 10, &val);
2600 if (err < 0)
2601 return err;
2602
2603 val = step_time_to_reg(val, data->pwm_mode[nr]);
2604 mutex_lock(&data->update_lock);
2605 data->fan_time[index][nr] = val;
2606 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2607 mutex_unlock(&data->update_lock);
2608 return count;
2609}
2610
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002611static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002612show_name(struct device *dev, struct device_attribute *attr, char *buf)
2613{
2614 struct nct6775_data *data = dev_get_drvdata(dev);
2615
2616 return sprintf(buf, "%s\n", data->name);
2617}
2618
2619static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2620
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002621static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2622 store_fan_time, 0, 0);
2623static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2624 store_fan_time, 1, 0);
2625static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2626 store_fan_time, 2, 0);
2627static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2628 store_fan_time, 3, 0);
2629static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2630 store_fan_time, 4, 0);
2631
2632static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2633 store_fan_time, 0, 1);
2634static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2635 store_fan_time, 1, 1);
2636static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2637 store_fan_time, 2, 1);
2638static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2639 store_fan_time, 3, 1);
2640static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2641 store_fan_time, 4, 1);
2642
2643static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO,
2644 show_fan_time, store_fan_time, 0, 2);
2645static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO,
2646 show_fan_time, store_fan_time, 1, 2);
2647static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO,
2648 show_fan_time, store_fan_time, 2, 2);
2649static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO,
2650 show_fan_time, store_fan_time, 3, 2);
2651static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO,
2652 show_fan_time, store_fan_time, 4, 2);
2653
2654static SENSOR_DEVICE_ATTR_2(pwm1_start, S_IWUSR | S_IRUGO, show_pwm,
2655 store_pwm, 0, 1);
2656static SENSOR_DEVICE_ATTR_2(pwm2_start, S_IWUSR | S_IRUGO, show_pwm,
2657 store_pwm, 1, 1);
2658static SENSOR_DEVICE_ATTR_2(pwm3_start, S_IWUSR | S_IRUGO, show_pwm,
2659 store_pwm, 2, 1);
2660static SENSOR_DEVICE_ATTR_2(pwm4_start, S_IWUSR | S_IRUGO, show_pwm,
2661 store_pwm, 3, 1);
2662static SENSOR_DEVICE_ATTR_2(pwm5_start, S_IWUSR | S_IRUGO, show_pwm,
2663 store_pwm, 4, 1);
2664
2665static SENSOR_DEVICE_ATTR_2(pwm1_floor, S_IWUSR | S_IRUGO, show_pwm,
2666 store_pwm, 0, 2);
2667static SENSOR_DEVICE_ATTR_2(pwm2_floor, S_IWUSR | S_IRUGO, show_pwm,
2668 store_pwm, 1, 2);
2669static SENSOR_DEVICE_ATTR_2(pwm3_floor, S_IWUSR | S_IRUGO, show_pwm,
2670 store_pwm, 2, 2);
2671static SENSOR_DEVICE_ATTR_2(pwm4_floor, S_IWUSR | S_IRUGO, show_pwm,
2672 store_pwm, 3, 2);
2673static SENSOR_DEVICE_ATTR_2(pwm5_floor, S_IWUSR | S_IRUGO, show_pwm,
2674 store_pwm, 4, 2);
2675
2676static SENSOR_DEVICE_ATTR_2(pwm1_temp_tolerance, S_IWUSR | S_IRUGO,
2677 show_temp_tolerance, store_temp_tolerance, 0, 0);
2678static SENSOR_DEVICE_ATTR_2(pwm2_temp_tolerance, S_IWUSR | S_IRUGO,
2679 show_temp_tolerance, store_temp_tolerance, 1, 0);
2680static SENSOR_DEVICE_ATTR_2(pwm3_temp_tolerance, S_IWUSR | S_IRUGO,
2681 show_temp_tolerance, store_temp_tolerance, 2, 0);
2682static SENSOR_DEVICE_ATTR_2(pwm4_temp_tolerance, S_IWUSR | S_IRUGO,
2683 show_temp_tolerance, store_temp_tolerance, 3, 0);
2684static SENSOR_DEVICE_ATTR_2(pwm5_temp_tolerance, S_IWUSR | S_IRUGO,
2685 show_temp_tolerance, store_temp_tolerance, 4, 0);
2686
2687static SENSOR_DEVICE_ATTR_2(pwm1_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2688 show_temp_tolerance, store_temp_tolerance, 0, 1);
2689static SENSOR_DEVICE_ATTR_2(pwm2_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2690 show_temp_tolerance, store_temp_tolerance, 1, 1);
2691static SENSOR_DEVICE_ATTR_2(pwm3_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2692 show_temp_tolerance, store_temp_tolerance, 2, 1);
2693static SENSOR_DEVICE_ATTR_2(pwm4_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2694 show_temp_tolerance, store_temp_tolerance, 3, 1);
2695static SENSOR_DEVICE_ATTR_2(pwm5_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2696 show_temp_tolerance, store_temp_tolerance, 4, 1);
2697
2698/* pwm_max is not supported on all chips */
2699static struct sensor_device_attribute_2 sda_pwm_max[] = {
2700 SENSOR_ATTR_2(pwm1_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2701 0, 3),
2702 SENSOR_ATTR_2(pwm2_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2703 1, 3),
2704 SENSOR_ATTR_2(pwm3_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2705 2, 3),
2706 SENSOR_ATTR_2(pwm4_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2707 3, 3),
2708 SENSOR_ATTR_2(pwm5_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2709 4, 3),
2710};
2711
2712/* pwm_step is not supported on all chips */
2713static struct sensor_device_attribute_2 sda_pwm_step[] = {
2714 SENSOR_ATTR_2(pwm1_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 4),
2715 SENSOR_ATTR_2(pwm2_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 4),
2716 SENSOR_ATTR_2(pwm3_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 4),
2717 SENSOR_ATTR_2(pwm4_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 4),
2718 SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4),
2719};
2720
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002721static struct attribute *nct6775_attributes_pwm[5][20] = {
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002722 {
2723 &sensor_dev_attr_pwm1.dev_attr.attr,
2724 &sensor_dev_attr_pwm1_mode.dev_attr.attr,
2725 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002726 &sensor_dev_attr_pwm1_temp_sel.dev_attr.attr,
2727 &sensor_dev_attr_pwm1_temp_tolerance.dev_attr.attr,
2728 &sensor_dev_attr_pwm1_crit_temp_tolerance.dev_attr.attr,
2729 &sensor_dev_attr_pwm1_target_temp.dev_attr.attr,
2730 &sensor_dev_attr_fan1_target.dev_attr.attr,
2731 &sensor_dev_attr_fan1_tolerance.dev_attr.attr,
2732 &sensor_dev_attr_pwm1_stop_time.dev_attr.attr,
2733 &sensor_dev_attr_pwm1_step_up_time.dev_attr.attr,
2734 &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr,
2735 &sensor_dev_attr_pwm1_start.dev_attr.attr,
2736 &sensor_dev_attr_pwm1_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002737 &sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr,
2738 &sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr,
2739 &sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr,
2740 &sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr,
2741 &sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002742 NULL
2743 },
2744 {
2745 &sensor_dev_attr_pwm2.dev_attr.attr,
2746 &sensor_dev_attr_pwm2_mode.dev_attr.attr,
2747 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002748 &sensor_dev_attr_pwm2_temp_sel.dev_attr.attr,
2749 &sensor_dev_attr_pwm2_temp_tolerance.dev_attr.attr,
2750 &sensor_dev_attr_pwm2_crit_temp_tolerance.dev_attr.attr,
2751 &sensor_dev_attr_pwm2_target_temp.dev_attr.attr,
2752 &sensor_dev_attr_fan2_target.dev_attr.attr,
2753 &sensor_dev_attr_fan2_tolerance.dev_attr.attr,
2754 &sensor_dev_attr_pwm2_stop_time.dev_attr.attr,
2755 &sensor_dev_attr_pwm2_step_up_time.dev_attr.attr,
2756 &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr,
2757 &sensor_dev_attr_pwm2_start.dev_attr.attr,
2758 &sensor_dev_attr_pwm2_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002759 &sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr,
2760 &sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr,
2761 &sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr,
2762 &sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr,
2763 &sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002764 NULL
2765 },
2766 {
2767 &sensor_dev_attr_pwm3.dev_attr.attr,
2768 &sensor_dev_attr_pwm3_mode.dev_attr.attr,
2769 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002770 &sensor_dev_attr_pwm3_temp_sel.dev_attr.attr,
2771 &sensor_dev_attr_pwm3_temp_tolerance.dev_attr.attr,
2772 &sensor_dev_attr_pwm3_crit_temp_tolerance.dev_attr.attr,
2773 &sensor_dev_attr_pwm3_target_temp.dev_attr.attr,
2774 &sensor_dev_attr_fan3_target.dev_attr.attr,
2775 &sensor_dev_attr_fan3_tolerance.dev_attr.attr,
2776 &sensor_dev_attr_pwm3_stop_time.dev_attr.attr,
2777 &sensor_dev_attr_pwm3_step_up_time.dev_attr.attr,
2778 &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr,
2779 &sensor_dev_attr_pwm3_start.dev_attr.attr,
2780 &sensor_dev_attr_pwm3_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002781 &sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr,
2782 &sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr,
2783 &sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr,
2784 &sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr,
2785 &sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002786 NULL
2787 },
2788 {
2789 &sensor_dev_attr_pwm4.dev_attr.attr,
2790 &sensor_dev_attr_pwm4_mode.dev_attr.attr,
2791 &sensor_dev_attr_pwm4_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002792 &sensor_dev_attr_pwm4_temp_sel.dev_attr.attr,
2793 &sensor_dev_attr_pwm4_temp_tolerance.dev_attr.attr,
2794 &sensor_dev_attr_pwm4_crit_temp_tolerance.dev_attr.attr,
2795 &sensor_dev_attr_pwm4_target_temp.dev_attr.attr,
2796 &sensor_dev_attr_fan4_target.dev_attr.attr,
2797 &sensor_dev_attr_fan4_tolerance.dev_attr.attr,
2798 &sensor_dev_attr_pwm4_stop_time.dev_attr.attr,
2799 &sensor_dev_attr_pwm4_step_up_time.dev_attr.attr,
2800 &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr,
2801 &sensor_dev_attr_pwm4_start.dev_attr.attr,
2802 &sensor_dev_attr_pwm4_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002803 &sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr,
2804 &sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr,
2805 &sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr,
2806 &sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr,
2807 &sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002808 NULL
2809 },
2810 {
2811 &sensor_dev_attr_pwm5.dev_attr.attr,
2812 &sensor_dev_attr_pwm5_mode.dev_attr.attr,
2813 &sensor_dev_attr_pwm5_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002814 &sensor_dev_attr_pwm5_temp_sel.dev_attr.attr,
2815 &sensor_dev_attr_pwm5_temp_tolerance.dev_attr.attr,
2816 &sensor_dev_attr_pwm5_crit_temp_tolerance.dev_attr.attr,
2817 &sensor_dev_attr_pwm5_target_temp.dev_attr.attr,
2818 &sensor_dev_attr_fan5_target.dev_attr.attr,
2819 &sensor_dev_attr_fan5_tolerance.dev_attr.attr,
2820 &sensor_dev_attr_pwm5_stop_time.dev_attr.attr,
2821 &sensor_dev_attr_pwm5_step_up_time.dev_attr.attr,
2822 &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr,
2823 &sensor_dev_attr_pwm5_start.dev_attr.attr,
2824 &sensor_dev_attr_pwm5_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002825 &sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr,
2826 &sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr,
2827 &sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr,
2828 &sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr,
2829 &sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002830 NULL
2831 },
2832};
2833
2834static const struct attribute_group nct6775_group_pwm[5] = {
2835 { .attrs = nct6775_attributes_pwm[0] },
2836 { .attrs = nct6775_attributes_pwm[1] },
2837 { .attrs = nct6775_attributes_pwm[2] },
2838 { .attrs = nct6775_attributes_pwm[3] },
2839 { .attrs = nct6775_attributes_pwm[4] },
2840};
2841
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002842static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002843show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2844{
2845 struct nct6775_data *data = nct6775_update_device(dev);
2846 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2847
2848 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2849}
2850
2851static ssize_t
2852store_auto_pwm(struct device *dev, struct device_attribute *attr,
2853 const char *buf, size_t count)
2854{
2855 struct nct6775_data *data = dev_get_drvdata(dev);
2856 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2857 int nr = sattr->nr;
2858 int point = sattr->index;
2859 unsigned long val;
2860 int err;
2861 u8 reg;
2862
2863 err = kstrtoul(buf, 10, &val);
2864 if (err < 0)
2865 return err;
2866 if (val > 255)
2867 return -EINVAL;
2868
2869 if (point == data->auto_pwm_num) {
2870 if (data->kind != nct6775 && !val)
2871 return -EINVAL;
2872 if (data->kind != nct6779 && val)
2873 val = 0xff;
2874 }
2875
2876 mutex_lock(&data->update_lock);
2877 data->auto_pwm[nr][point] = val;
2878 if (point < data->auto_pwm_num) {
2879 nct6775_write_value(data,
2880 NCT6775_AUTO_PWM(data, nr, point),
2881 data->auto_pwm[nr][point]);
2882 } else {
2883 switch (data->kind) {
2884 case nct6775:
2885 /* disable if needed (pwm == 0) */
2886 reg = nct6775_read_value(data,
2887 NCT6775_REG_CRITICAL_ENAB[nr]);
2888 if (val)
2889 reg |= 0x02;
2890 else
2891 reg &= ~0x02;
2892 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2893 reg);
2894 break;
2895 case nct6776:
2896 break; /* always enabled, nothing to do */
2897 case nct6779:
2898 nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr],
2899 val);
2900 reg = nct6775_read_value(data,
2901 NCT6779_REG_CRITICAL_PWM_ENABLE[nr]);
2902 if (val == 255)
2903 reg &= ~0x01;
2904 else
2905 reg |= 0x01;
2906 nct6775_write_value(data,
2907 NCT6779_REG_CRITICAL_PWM_ENABLE[nr],
2908 reg);
2909 break;
2910 }
2911 }
2912 mutex_unlock(&data->update_lock);
2913 return count;
2914}
2915
2916static ssize_t
2917show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2918{
2919 struct nct6775_data *data = nct6775_update_device(dev);
2920 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2921 int nr = sattr->nr;
2922 int point = sattr->index;
2923
2924 /*
2925 * We don't know for sure if the temperature is signed or unsigned.
2926 * Assume it is unsigned.
2927 */
2928 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2929}
2930
2931static ssize_t
2932store_auto_temp(struct device *dev, struct device_attribute *attr,
2933 const char *buf, size_t count)
2934{
2935 struct nct6775_data *data = dev_get_drvdata(dev);
2936 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2937 int nr = sattr->nr;
2938 int point = sattr->index;
2939 unsigned long val;
2940 int err;
2941
2942 err = kstrtoul(buf, 10, &val);
2943 if (err)
2944 return err;
2945 if (val > 255000)
2946 return -EINVAL;
2947
2948 mutex_lock(&data->update_lock);
2949 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2950 if (point < data->auto_pwm_num) {
2951 nct6775_write_value(data,
2952 NCT6775_AUTO_TEMP(data, nr, point),
2953 data->auto_temp[nr][point]);
2954 } else {
2955 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2956 data->auto_temp[nr][point]);
2957 }
2958 mutex_unlock(&data->update_lock);
2959 return count;
2960}
2961
2962/*
2963 * The number of auto-point trip points is chip dependent.
2964 * Need to check support while generating/removing attribute files.
2965 */
2966static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = {
2967 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
2968 show_auto_pwm, store_auto_pwm, 0, 0),
2969 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
2970 show_auto_temp, store_auto_temp, 0, 0),
2971 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
2972 show_auto_pwm, store_auto_pwm, 0, 1),
2973 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
2974 show_auto_temp, store_auto_temp, 0, 1),
2975 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
2976 show_auto_pwm, store_auto_pwm, 0, 2),
2977 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
2978 show_auto_temp, store_auto_temp, 0, 2),
2979 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
2980 show_auto_pwm, store_auto_pwm, 0, 3),
2981 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
2982 show_auto_temp, store_auto_temp, 0, 3),
2983 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
2984 show_auto_pwm, store_auto_pwm, 0, 4),
2985 SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
2986 show_auto_temp, store_auto_temp, 0, 4),
2987 SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
2988 show_auto_pwm, store_auto_pwm, 0, 5),
2989 SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
2990 show_auto_temp, store_auto_temp, 0, 5),
2991 SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
2992 show_auto_pwm, store_auto_pwm, 0, 6),
2993 SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
2994 show_auto_temp, store_auto_temp, 0, 6),
2995
2996 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
2997 show_auto_pwm, store_auto_pwm, 1, 0),
2998 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO,
2999 show_auto_temp, store_auto_temp, 1, 0),
3000 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
3001 show_auto_pwm, store_auto_pwm, 1, 1),
3002 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO,
3003 show_auto_temp, store_auto_temp, 1, 1),
3004 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO,
3005 show_auto_pwm, store_auto_pwm, 1, 2),
3006 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO,
3007 show_auto_temp, store_auto_temp, 1, 2),
3008 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO,
3009 show_auto_pwm, store_auto_pwm, 1, 3),
3010 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO,
3011 show_auto_temp, store_auto_temp, 1, 3),
3012 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO,
3013 show_auto_pwm, store_auto_pwm, 1, 4),
3014 SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO,
3015 show_auto_temp, store_auto_temp, 1, 4),
3016 SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO,
3017 show_auto_pwm, store_auto_pwm, 1, 5),
3018 SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO,
3019 show_auto_temp, store_auto_temp, 1, 5),
3020 SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO,
3021 show_auto_pwm, store_auto_pwm, 1, 6),
3022 SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO,
3023 show_auto_temp, store_auto_temp, 1, 6),
3024
3025 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
3026 show_auto_pwm, store_auto_pwm, 2, 0),
3027 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO,
3028 show_auto_temp, store_auto_temp, 2, 0),
3029 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
3030 show_auto_pwm, store_auto_pwm, 2, 1),
3031 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO,
3032 show_auto_temp, store_auto_temp, 2, 1),
3033 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO,
3034 show_auto_pwm, store_auto_pwm, 2, 2),
3035 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO,
3036 show_auto_temp, store_auto_temp, 2, 2),
3037 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO,
3038 show_auto_pwm, store_auto_pwm, 2, 3),
3039 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO,
3040 show_auto_temp, store_auto_temp, 2, 3),
3041 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO,
3042 show_auto_pwm, store_auto_pwm, 2, 4),
3043 SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO,
3044 show_auto_temp, store_auto_temp, 2, 4),
3045 SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO,
3046 show_auto_pwm, store_auto_pwm, 2, 5),
3047 SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO,
3048 show_auto_temp, store_auto_temp, 2, 5),
3049 SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO,
3050 show_auto_pwm, store_auto_pwm, 2, 6),
3051 SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO,
3052 show_auto_temp, store_auto_temp, 2, 6),
3053
3054 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
3055 show_auto_pwm, store_auto_pwm, 3, 0),
3056 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO,
3057 show_auto_temp, store_auto_temp, 3, 0),
3058 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
3059 show_auto_pwm, store_auto_pwm, 3, 1),
3060 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO,
3061 show_auto_temp, store_auto_temp, 3, 1),
3062 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO,
3063 show_auto_pwm, store_auto_pwm, 3, 2),
3064 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO,
3065 show_auto_temp, store_auto_temp, 3, 2),
3066 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO,
3067 show_auto_pwm, store_auto_pwm, 3, 3),
3068 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO,
3069 show_auto_temp, store_auto_temp, 3, 3),
3070 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO,
3071 show_auto_pwm, store_auto_pwm, 3, 4),
3072 SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO,
3073 show_auto_temp, store_auto_temp, 3, 4),
3074 SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO,
3075 show_auto_pwm, store_auto_pwm, 3, 5),
3076 SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO,
3077 show_auto_temp, store_auto_temp, 3, 5),
3078 SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO,
3079 show_auto_pwm, store_auto_pwm, 3, 6),
3080 SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO,
3081 show_auto_temp, store_auto_temp, 3, 6),
3082
3083 SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO,
3084 show_auto_pwm, store_auto_pwm, 4, 0),
3085 SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO,
3086 show_auto_temp, store_auto_temp, 4, 0),
3087 SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO,
3088 show_auto_pwm, store_auto_pwm, 4, 1),
3089 SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO,
3090 show_auto_temp, store_auto_temp, 4, 1),
3091 SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO,
3092 show_auto_pwm, store_auto_pwm, 4, 2),
3093 SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO,
3094 show_auto_temp, store_auto_temp, 4, 2),
3095 SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO,
3096 show_auto_pwm, store_auto_pwm, 4, 3),
3097 SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO,
3098 show_auto_temp, store_auto_temp, 4, 3),
3099 SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO,
3100 show_auto_pwm, store_auto_pwm, 4, 4),
3101 SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO,
3102 show_auto_temp, store_auto_temp, 4, 4),
3103 SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO,
3104 show_auto_pwm, store_auto_pwm, 4, 5),
3105 SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO,
3106 show_auto_temp, store_auto_temp, 4, 5),
3107 SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO,
3108 show_auto_pwm, store_auto_pwm, 4, 6),
3109 SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO,
3110 show_auto_temp, store_auto_temp, 4, 6),
3111};
3112
3113static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003114show_vid(struct device *dev, struct device_attribute *attr, char *buf)
3115{
3116 struct nct6775_data *data = dev_get_drvdata(dev);
3117 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3118}
3119
3120static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3121
Guenter Roecka6bd5872012-12-04 03:13:34 -08003122/* Case open detection */
3123
3124static ssize_t
3125clear_caseopen(struct device *dev, struct device_attribute *attr,
3126 const char *buf, size_t count)
3127{
3128 struct nct6775_data *data = dev_get_drvdata(dev);
3129 struct nct6775_sio_data *sio_data = dev->platform_data;
3130 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3131 unsigned long val;
3132 u8 reg;
3133 int ret;
3134
3135 if (kstrtoul(buf, 10, &val) || val != 0)
3136 return -EINVAL;
3137
3138 mutex_lock(&data->update_lock);
3139
3140 /*
3141 * Use CR registers to clear caseopen status.
3142 * The CR registers are the same for all chips, and not all chips
3143 * support clearing the caseopen status through "regular" registers.
3144 */
3145 ret = superio_enter(sio_data->sioreg);
3146 if (ret) {
3147 count = ret;
3148 goto error;
3149 }
3150
3151 superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
3152 reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
3153 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
3154 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3155 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
3156 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3157 superio_exit(sio_data->sioreg);
3158
3159 data->valid = false; /* Force cache refresh */
3160error:
3161 mutex_unlock(&data->update_lock);
3162 return count;
3163}
3164
3165static struct sensor_device_attribute sda_caseopen[] = {
3166 SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3167 clear_caseopen, INTRUSION_ALARM_BASE),
3168 SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3169 clear_caseopen, INTRUSION_ALARM_BASE + 1),
3170};
3171
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003172/*
3173 * Driver and device management
3174 */
3175
3176static void nct6775_device_remove_files(struct device *dev)
3177{
3178 /*
3179 * some entries in the following arrays may not have been used in
3180 * device_create_file(), but device_remove_file() will ignore them
3181 */
3182 int i;
3183 struct nct6775_data *data = dev_get_drvdata(dev);
3184
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003185 for (i = 0; i < data->pwm_num; i++)
3186 sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]);
3187
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003188 for (i = 0; i < ARRAY_SIZE(sda_pwm_max); i++)
3189 device_remove_file(dev, &sda_pwm_max[i].dev_attr);
3190
3191 for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++)
3192 device_remove_file(dev, &sda_pwm_step[i].dev_attr);
3193
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003194 for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++)
3195 device_remove_file(dev, &sda_weight_duty_base[i].dev_attr);
3196
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003197 for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++)
3198 device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr);
3199
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003200 for (i = 0; i < data->in_num; i++)
3201 sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]);
3202
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003203 for (i = 0; i < 5; i++) {
3204 device_remove_file(dev, &sda_fan_input[i].dev_attr);
3205 device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
3206 device_remove_file(dev, &sda_fan_div[i].dev_attr);
3207 device_remove_file(dev, &sda_fan_min[i].dev_attr);
Guenter Roeck5c25d952012-12-11 07:29:06 -08003208 device_remove_file(dev, &sda_fan_pulses[i].dev_attr);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003209 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003210 for (i = 0; i < NUM_TEMP; i++) {
3211 if (!(data->have_temp & (1 << i)))
3212 continue;
3213 device_remove_file(dev, &sda_temp_input[i].dev_attr);
3214 device_remove_file(dev, &sda_temp_label[i].dev_attr);
3215 device_remove_file(dev, &sda_temp_max[i].dev_attr);
3216 device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
3217 device_remove_file(dev, &sda_temp_crit[i].dev_attr);
3218 if (!(data->have_temp_fixed & (1 << i)))
3219 continue;
3220 device_remove_file(dev, &sda_temp_type[i].dev_attr);
3221 device_remove_file(dev, &sda_temp_offset[i].dev_attr);
3222 if (i >= NUM_TEMP_ALARM)
3223 continue;
3224 device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
3225 }
3226
Guenter Roecka6bd5872012-12-04 03:13:34 -08003227 device_remove_file(dev, &sda_caseopen[0].dev_attr);
3228 device_remove_file(dev, &sda_caseopen[1].dev_attr);
3229
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003230 device_remove_file(dev, &dev_attr_name);
3231 device_remove_file(dev, &dev_attr_cpu0_vid);
3232}
3233
3234/* Get the monitoring functions started */
3235static inline void nct6775_init_device(struct nct6775_data *data)
3236{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003237 int i;
3238 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003239
3240 /* Start monitoring if needed */
3241 if (data->REG_CONFIG) {
3242 tmp = nct6775_read_value(data, data->REG_CONFIG);
3243 if (!(tmp & 0x01))
3244 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3245 }
3246
Guenter Roeckaa136e52012-12-04 03:26:05 -08003247 /* Enable temperature sensors if needed */
3248 for (i = 0; i < NUM_TEMP; i++) {
3249 if (!(data->have_temp & (1 << i)))
3250 continue;
3251 if (!data->reg_temp_config[i])
3252 continue;
3253 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3254 if (tmp & 0x01)
3255 nct6775_write_value(data, data->reg_temp_config[i],
3256 tmp & 0xfe);
3257 }
3258
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003259 /* Enable VBAT monitoring if needed */
3260 tmp = nct6775_read_value(data, data->REG_VBAT);
3261 if (!(tmp & 0x01))
3262 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003263
3264 diode = nct6775_read_value(data, data->REG_DIODE);
3265
3266 for (i = 0; i < data->temp_fixed_num; i++) {
3267 if (!(data->have_temp_fixed & (1 << i)))
3268 continue;
3269 if ((tmp & (0x02 << i))) /* diode */
3270 data->temp_type[i] = 3 - ((diode >> i) & 0x02);
3271 else /* thermistor */
3272 data->temp_type[i] = 4;
3273 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003274}
3275
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003276static int
3277nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
3278 struct nct6775_data *data)
3279{
3280 int regval;
3281 bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003282 bool pwm3pin, pwm4pin, pwm5pin;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003283 int ret;
3284
3285 ret = superio_enter(sio_data->sioreg);
3286 if (ret)
3287 return ret;
3288
3289 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3290 if (data->kind == nct6775) {
3291 regval = superio_inb(sio_data->sioreg, 0x2c);
3292
3293 fan3pin = regval & (1 << 6);
3294 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003295 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003296
3297 /* On NCT6775, fan4 shares pins with the fdc interface */
3298 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
3299 fan4min = 0;
3300 fan5pin = 0;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003301 pwm4pin = 0;
3302 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003303 } else if (data->kind == nct6776) {
3304 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
3305
3306 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3307 regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
3308
3309 if (regval & 0x80)
3310 fan3pin = gpok;
3311 else
3312 fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
3313
3314 if (regval & 0x40)
3315 fan4pin = gpok;
3316 else
3317 fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
3318
3319 if (regval & 0x20)
3320 fan5pin = gpok;
3321 else
3322 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
3323
3324 fan4min = fan4pin;
3325 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003326 pwm3pin = fan3pin;
3327 pwm4pin = 0;
3328 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003329 } else { /* NCT6779D */
3330 regval = superio_inb(sio_data->sioreg, 0x1c);
3331
3332 fan3pin = !(regval & (1 << 5));
3333 fan4pin = !(regval & (1 << 6));
3334 fan5pin = !(regval & (1 << 7));
3335
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003336 pwm3pin = !(regval & (1 << 0));
3337 pwm4pin = !(regval & (1 << 1));
3338 pwm5pin = !(regval & (1 << 2));
3339
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003340 fan3min = fan3pin;
3341 fan4min = fan4pin;
3342 }
3343
3344 superio_exit(sio_data->sioreg);
3345
3346 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
3347 data->has_fan |= fan3pin << 2;
3348 data->has_fan_min |= fan3min << 2;
3349
3350 data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
3351 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
3352
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003353 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
3354
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003355 return 0;
3356}
3357
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003358static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3359 int *available, int *mask)
3360{
3361 int i;
3362 u8 src;
3363
3364 for (i = 0; i < data->pwm_num && *available; i++) {
3365 int index;
3366
3367 if (!regp[i])
3368 continue;
3369 src = nct6775_read_value(data, regp[i]);
3370 src &= 0x1f;
3371 if (!src || (*mask & (1 << src)))
3372 continue;
3373 if (src >= data->temp_label_num ||
3374 !strlen(data->temp_label[src]))
3375 continue;
3376
3377 index = __ffs(*available);
3378 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3379 *available &= ~(1 << index);
3380 *mask |= 1 << src;
3381 }
3382}
3383
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003384static int nct6775_probe(struct platform_device *pdev)
3385{
3386 struct device *dev = &pdev->dev;
3387 struct nct6775_sio_data *sio_data = dev->platform_data;
3388 struct nct6775_data *data;
3389 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003390 int i, s, err = 0;
3391 int src, mask, available;
3392 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3393 const u16 *reg_temp_alternate, *reg_temp_crit;
3394 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003395 bool have_vid = false;
3396 u8 cr2a;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003397
3398 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3399 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3400 DRVNAME))
3401 return -EBUSY;
3402
3403 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3404 GFP_KERNEL);
3405 if (!data)
3406 return -ENOMEM;
3407
3408 data->kind = sio_data->kind;
3409 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003410 mutex_init(&data->update_lock);
3411 data->name = nct6775_device_names[data->kind];
3412 data->bank = 0xff; /* Force initial bank selection */
3413 platform_set_drvdata(pdev, data);
3414
3415 switch (data->kind) {
3416 case nct6775:
3417 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003418 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003419 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003420 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003421 data->temp_fixed_num = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003422
3423 data->ALARM_BITS = NCT6775_ALARM_BITS;
3424
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003425 data->fan_from_reg = fan_from_reg16;
3426 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003427 data->target_temp_mask = 0x7f;
3428 data->tolerance_mask = 0x0f;
3429 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003430
Guenter Roeckaa136e52012-12-04 03:26:05 -08003431 data->temp_label = nct6775_temp_label;
3432 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3433
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003434 data->REG_CONFIG = NCT6775_REG_CONFIG;
3435 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003436 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003437 data->REG_VIN = NCT6775_REG_IN;
3438 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3439 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003440 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003441 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003442 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003443 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003444 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003445 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3446 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3447 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003448 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003449 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3450 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3451 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3452 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003453 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003454 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3455 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3456 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003457 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3458 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3459 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3460 data->REG_CRITICAL_TEMP_TOLERANCE
3461 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003462 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3463 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003464 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003465 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3466 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3467 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3468 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003469 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003470
3471 reg_temp = NCT6775_REG_TEMP;
3472 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3473 reg_temp_over = NCT6775_REG_TEMP_OVER;
3474 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3475 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3476 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3477 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3478
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003479 break;
3480 case nct6776:
3481 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003482 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003483 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003484 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003485 data->temp_fixed_num = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003486
3487 data->ALARM_BITS = NCT6776_ALARM_BITS;
3488
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003489 data->fan_from_reg = fan_from_reg13;
3490 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003491 data->target_temp_mask = 0xff;
3492 data->tolerance_mask = 0x07;
3493 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003494
Guenter Roeckaa136e52012-12-04 03:26:05 -08003495 data->temp_label = nct6776_temp_label;
3496 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3497
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003498 data->REG_CONFIG = NCT6775_REG_CONFIG;
3499 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003500 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003501 data->REG_VIN = NCT6775_REG_IN;
3502 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3503 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003504 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003505 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003506 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003507 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003508 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003509 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3510 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3511 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3512 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003513 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003514 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3515 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003516 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3517 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003518 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3519 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3520 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003521 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3522 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3523 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3524 data->REG_CRITICAL_TEMP_TOLERANCE
3525 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003526 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3527 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003528 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003529 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3530 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3531 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3532 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003533 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003534
3535 reg_temp = NCT6775_REG_TEMP;
3536 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3537 reg_temp_over = NCT6775_REG_TEMP_OVER;
3538 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3539 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3540 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3541 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3542
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003543 break;
3544 case nct6779:
3545 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003546 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003547 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003548 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003549 data->temp_fixed_num = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003550
3551 data->ALARM_BITS = NCT6779_ALARM_BITS;
3552
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003553 data->fan_from_reg = fan_from_reg13;
3554 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003555 data->target_temp_mask = 0xff;
3556 data->tolerance_mask = 0x07;
3557 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003558
Guenter Roeckaa136e52012-12-04 03:26:05 -08003559 data->temp_label = nct6779_temp_label;
3560 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3561
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003562 data->REG_CONFIG = NCT6775_REG_CONFIG;
3563 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003564 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003565 data->REG_VIN = NCT6779_REG_IN;
3566 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3567 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003568 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003569 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003570 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003571 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003572 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003573 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3574 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3575 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3576 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003577 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003578 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3579 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003580 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3581 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003582 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3583 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3584 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003585 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3586 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3587 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3588 data->REG_CRITICAL_TEMP_TOLERANCE
3589 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003590 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3591 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003592 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003593 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3594 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3595 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3596 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003597 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003598
3599 reg_temp = NCT6779_REG_TEMP;
3600 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3601 reg_temp_over = NCT6779_REG_TEMP_OVER;
3602 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3603 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3604 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3605 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3606
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003607 break;
3608 default:
3609 return -ENODEV;
3610 }
3611 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003612 data->have_temp = 0;
3613
3614 /*
3615 * On some boards, not all available temperature sources are monitored,
3616 * even though some of the monitoring registers are unused.
3617 * Get list of unused monitoring registers, then detect if any fan
3618 * controls are configured to use unmonitored temperature sources.
3619 * If so, assign the unmonitored temperature sources to available
3620 * monitoring registers.
3621 */
3622 mask = 0;
3623 available = 0;
3624 for (i = 0; i < num_reg_temp; i++) {
3625 if (reg_temp[i] == 0)
3626 continue;
3627
3628 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3629 if (!src || (mask & (1 << src)))
3630 available |= 1 << i;
3631
3632 mask |= 1 << src;
3633 }
3634
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003635 /*
3636 * Now find unmonitored temperature registers and enable monitoring
3637 * if additional monitoring registers are available.
3638 */
3639 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3640 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3641
Guenter Roeckaa136e52012-12-04 03:26:05 -08003642 mask = 0;
3643 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3644 for (i = 0; i < num_reg_temp; i++) {
3645 if (reg_temp[i] == 0)
3646 continue;
3647
3648 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3649 if (!src || (mask & (1 << src)))
3650 continue;
3651
3652 if (src >= data->temp_label_num ||
3653 !strlen(data->temp_label[src])) {
3654 dev_info(dev,
3655 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3656 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3657 continue;
3658 }
3659
3660 mask |= 1 << src;
3661
3662 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3663 if (src <= data->temp_fixed_num) {
3664 data->have_temp |= 1 << (src - 1);
3665 data->have_temp_fixed |= 1 << (src - 1);
3666 data->reg_temp[0][src - 1] = reg_temp[i];
3667 data->reg_temp[1][src - 1] = reg_temp_over[i];
3668 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
3669 data->reg_temp_config[src - 1] = reg_temp_config[i];
3670 data->temp_src[src - 1] = src;
3671 continue;
3672 }
3673
3674 if (s >= NUM_TEMP)
3675 continue;
3676
3677 /* Use dynamic index for other sources */
3678 data->have_temp |= 1 << s;
3679 data->reg_temp[0][s] = reg_temp[i];
3680 data->reg_temp[1][s] = reg_temp_over[i];
3681 data->reg_temp[2][s] = reg_temp_hyst[i];
3682 data->reg_temp_config[s] = reg_temp_config[i];
3683 if (reg_temp_crit[src - 1])
3684 data->reg_temp[3][s] = reg_temp_crit[src - 1];
3685
3686 data->temp_src[s] = src;
3687 s++;
3688 }
3689
3690#ifdef USE_ALTERNATE
3691 /*
3692 * Go through the list of alternate temp registers and enable
3693 * if possible.
3694 * The temperature is already monitored if the respective bit in <mask>
3695 * is set.
3696 */
3697 for (i = 0; i < data->temp_label_num - 1; i++) {
3698 if (!reg_temp_alternate[i])
3699 continue;
3700 if (mask & (1 << (i + 1)))
3701 continue;
3702 if (i < data->temp_fixed_num) {
3703 if (data->have_temp & (1 << i))
3704 continue;
3705 data->have_temp |= 1 << i;
3706 data->have_temp_fixed |= 1 << i;
3707 data->reg_temp[0][i] = reg_temp_alternate[i];
3708 data->reg_temp[1][i] = reg_temp_over[i];
3709 data->reg_temp[2][i] = reg_temp_hyst[i];
3710 data->temp_src[i] = i + 1;
3711 continue;
3712 }
3713
3714 if (s >= NUM_TEMP) /* Abort if no more space */
3715 break;
3716
3717 data->have_temp |= 1 << s;
3718 data->reg_temp[0][s] = reg_temp_alternate[i];
3719 data->temp_src[s] = i + 1;
3720 s++;
3721 }
3722#endif /* USE_ALTERNATE */
3723
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003724 /* Initialize the chip */
3725 nct6775_init_device(data);
3726
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003727 err = superio_enter(sio_data->sioreg);
3728 if (err)
3729 return err;
3730
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003731 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3732 switch (data->kind) {
3733 case nct6775:
3734 have_vid = (cr2a & 0x40);
3735 break;
3736 case nct6776:
3737 have_vid = (cr2a & 0x60) == 0x40;
3738 break;
3739 case nct6779:
3740 break;
3741 }
3742
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003743 /*
3744 * Read VID value
3745 * We can get the VID input values directly at logical device D 0xe3.
3746 */
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003747 if (have_vid) {
3748 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3749 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3750 data->vrm = vid_which_vrm();
3751 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003752
3753 if (fan_debounce) {
3754 u8 tmp;
3755
3756 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3757 tmp = superio_inb(sio_data->sioreg,
3758 NCT6775_REG_CR_FAN_DEBOUNCE);
3759 switch (data->kind) {
3760 case nct6775:
3761 tmp |= 0x1e;
3762 break;
3763 case nct6776:
3764 case nct6779:
3765 tmp |= 0x3e;
3766 break;
3767 }
3768 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3769 tmp);
3770 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3771 data->name);
3772 }
3773
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003774 superio_exit(sio_data->sioreg);
3775
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003776 if (have_vid) {
3777 err = device_create_file(dev, &dev_attr_cpu0_vid);
3778 if (err)
3779 return err;
3780 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003781
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003782 err = nct6775_check_fan_inputs(sio_data, data);
3783 if (err)
3784 goto exit_remove;
3785
3786 /* Read fan clock dividers immediately */
3787 nct6775_init_fan_common(dev, data);
3788
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003789 /* Register sysfs hooks */
3790 for (i = 0; i < data->pwm_num; i++) {
3791 if (!(data->has_pwm & (1 << i)))
3792 continue;
3793
3794 err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]);
3795 if (err)
3796 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003797
3798 if (data->REG_PWM[3]) {
3799 err = device_create_file(dev,
3800 &sda_pwm_max[i].dev_attr);
3801 if (err)
3802 goto exit_remove;
3803 }
3804 if (data->REG_PWM[4]) {
3805 err = device_create_file(dev,
3806 &sda_pwm_step[i].dev_attr);
3807 if (err)
3808 goto exit_remove;
3809 }
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003810 if (data->REG_PWM[6]) {
3811 err = device_create_file(dev,
3812 &sda_weight_duty_base[i].dev_attr);
3813 if (err)
3814 goto exit_remove;
3815 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003816 }
3817 for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) {
3818 struct sensor_device_attribute_2 *attr =
3819 &sda_auto_pwm_arrays[i];
3820
3821 if (!(data->has_pwm & (1 << attr->nr)))
3822 continue;
3823 if (attr->index > data->auto_pwm_num)
3824 continue;
3825 err = device_create_file(dev, &attr->dev_attr);
3826 if (err)
3827 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003828 }
3829
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003830 for (i = 0; i < data->in_num; i++) {
3831 if (!(data->have_in & (1 << i)))
3832 continue;
3833 err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]);
3834 if (err)
3835 goto exit_remove;
3836 }
3837
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003838 for (i = 0; i < 5; i++) {
3839 if (data->has_fan & (1 << i)) {
3840 err = device_create_file(dev,
3841 &sda_fan_input[i].dev_attr);
3842 if (err)
3843 goto exit_remove;
3844 err = device_create_file(dev,
3845 &sda_fan_alarm[i].dev_attr);
3846 if (err)
3847 goto exit_remove;
3848 if (data->kind != nct6776 &&
3849 data->kind != nct6779) {
3850 err = device_create_file(dev,
3851 &sda_fan_div[i].dev_attr);
3852 if (err)
3853 goto exit_remove;
3854 }
3855 if (data->has_fan_min & (1 << i)) {
3856 err = device_create_file(dev,
3857 &sda_fan_min[i].dev_attr);
3858 if (err)
3859 goto exit_remove;
3860 }
Guenter Roeck5c25d952012-12-11 07:29:06 -08003861 err = device_create_file(dev,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003862 &sda_fan_pulses[i].dev_attr);
Guenter Roeck5c25d952012-12-11 07:29:06 -08003863 if (err)
3864 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003865 }
3866 }
3867
Guenter Roeckaa136e52012-12-04 03:26:05 -08003868 for (i = 0; i < NUM_TEMP; i++) {
3869 if (!(data->have_temp & (1 << i)))
3870 continue;
3871 err = device_create_file(dev, &sda_temp_input[i].dev_attr);
3872 if (err)
3873 goto exit_remove;
3874 if (data->temp_label) {
3875 err = device_create_file(dev,
3876 &sda_temp_label[i].dev_attr);
3877 if (err)
3878 goto exit_remove;
3879 }
3880 if (data->reg_temp[1][i]) {
3881 err = device_create_file(dev,
3882 &sda_temp_max[i].dev_attr);
3883 if (err)
3884 goto exit_remove;
3885 }
3886 if (data->reg_temp[2][i]) {
3887 err = device_create_file(dev,
3888 &sda_temp_max_hyst[i].dev_attr);
3889 if (err)
3890 goto exit_remove;
3891 }
3892 if (data->reg_temp[3][i]) {
3893 err = device_create_file(dev,
3894 &sda_temp_crit[i].dev_attr);
3895 if (err)
3896 goto exit_remove;
3897 }
3898 if (!(data->have_temp_fixed & (1 << i)))
3899 continue;
3900 err = device_create_file(dev, &sda_temp_type[i].dev_attr);
3901 if (err)
3902 goto exit_remove;
3903 err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
3904 if (err)
3905 goto exit_remove;
3906 if (i >= NUM_TEMP_ALARM ||
3907 data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0)
3908 continue;
3909 err = device_create_file(dev, &sda_temp_alarm[i].dev_attr);
3910 if (err)
3911 goto exit_remove;
3912 }
3913
Guenter Roecka6bd5872012-12-04 03:13:34 -08003914 for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
3915 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0)
3916 continue;
3917 err = device_create_file(dev, &sda_caseopen[i].dev_attr);
3918 if (err)
3919 goto exit_remove;
3920 }
3921
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003922 err = device_create_file(dev, &dev_attr_name);
3923 if (err)
3924 goto exit_remove;
3925
3926 data->hwmon_dev = hwmon_device_register(dev);
3927 if (IS_ERR(data->hwmon_dev)) {
3928 err = PTR_ERR(data->hwmon_dev);
3929 goto exit_remove;
3930 }
3931
3932 return 0;
3933
3934exit_remove:
3935 nct6775_device_remove_files(dev);
3936 return err;
3937}
3938
3939static int nct6775_remove(struct platform_device *pdev)
3940{
3941 struct nct6775_data *data = platform_get_drvdata(pdev);
3942
3943 hwmon_device_unregister(data->hwmon_dev);
3944 nct6775_device_remove_files(&pdev->dev);
3945
3946 return 0;
3947}
3948
Guenter Roeck84d19d92012-12-04 08:01:39 -08003949#ifdef CONFIG_PM
3950static int nct6775_suspend(struct device *dev)
3951{
3952 struct nct6775_data *data = nct6775_update_device(dev);
3953 struct nct6775_sio_data *sio_data = dev->platform_data;
3954
3955 mutex_lock(&data->update_lock);
3956 data->vbat = nct6775_read_value(data, data->REG_VBAT);
3957 if (sio_data->kind == nct6775) {
3958 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3959 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3960 }
3961 mutex_unlock(&data->update_lock);
3962
3963 return 0;
3964}
3965
3966static int nct6775_resume(struct device *dev)
3967{
3968 struct nct6775_data *data = dev_get_drvdata(dev);
3969 struct nct6775_sio_data *sio_data = dev->platform_data;
3970 int i, j;
3971
3972 mutex_lock(&data->update_lock);
3973 data->bank = 0xff; /* Force initial bank selection */
3974
3975 /* Restore limits */
3976 for (i = 0; i < data->in_num; i++) {
3977 if (!(data->have_in & (1 << i)))
3978 continue;
3979
3980 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3981 data->in[i][1]);
3982 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3983 data->in[i][2]);
3984 }
3985
Guenter Roeckc409fd42013-04-09 05:04:00 -07003986 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003987 if (!(data->has_fan_min & (1 << i)))
3988 continue;
3989
3990 nct6775_write_value(data, data->REG_FAN_MIN[i],
3991 data->fan_min[i]);
3992 }
3993
3994 for (i = 0; i < NUM_TEMP; i++) {
3995 if (!(data->have_temp & (1 << i)))
3996 continue;
3997
Guenter Roeckc409fd42013-04-09 05:04:00 -07003998 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003999 if (data->reg_temp[j][i])
4000 nct6775_write_temp(data, data->reg_temp[j][i],
4001 data->temp[j][i]);
4002 }
4003
4004 /* Restore other settings */
4005 nct6775_write_value(data, data->REG_VBAT, data->vbat);
4006 if (sio_data->kind == nct6775) {
4007 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
4008 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
4009 }
4010
4011 /* Force re-reading all values */
4012 data->valid = false;
4013 mutex_unlock(&data->update_lock);
4014
4015 return 0;
4016}
4017
4018static const struct dev_pm_ops nct6775_dev_pm_ops = {
4019 .suspend = nct6775_suspend,
4020 .resume = nct6775_resume,
4021};
4022
4023#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4024#else
4025#define NCT6775_DEV_PM_OPS NULL
4026#endif /* CONFIG_PM */
4027
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004028static struct platform_driver nct6775_driver = {
4029 .driver = {
4030 .owner = THIS_MODULE,
4031 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004032 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004033 },
4034 .probe = nct6775_probe,
4035 .remove = nct6775_remove,
4036};
4037
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004038static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004039 "NCT6775F",
4040 "NCT6776D/F",
4041 "NCT6779D",
4042};
4043
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004044/* nct6775_find() looks for a '627 in the Super-I/O config space */
4045static int __init nct6775_find(int sioaddr, unsigned short *addr,
4046 struct nct6775_sio_data *sio_data)
4047{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004048 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004049 int err;
4050
4051 err = superio_enter(sioaddr);
4052 if (err)
4053 return err;
4054
4055 if (force_id)
4056 val = force_id;
4057 else
4058 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4059 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4060 switch (val & SIO_ID_MASK) {
4061 case SIO_NCT6775_ID:
4062 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004063 break;
4064 case SIO_NCT6776_ID:
4065 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004066 break;
4067 case SIO_NCT6779_ID:
4068 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004069 break;
4070 default:
4071 if (val != 0xffff)
4072 pr_debug("unsupported chip ID: 0x%04x\n", val);
4073 superio_exit(sioaddr);
4074 return -ENODEV;
4075 }
4076
4077 /* We have a known chip, find the HWM I/O address */
4078 superio_select(sioaddr, NCT6775_LD_HWM);
4079 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4080 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
4081 *addr = val & IOREGION_ALIGNMENT;
4082 if (*addr == 0) {
4083 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4084 superio_exit(sioaddr);
4085 return -ENODEV;
4086 }
4087
4088 /* Activate logical device if needed */
4089 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4090 if (!(val & 0x01)) {
4091 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4092 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4093 }
4094
4095 superio_exit(sioaddr);
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004096 pr_info("Found %s or compatible chip at %#x\n",
4097 nct6775_sio_names[sio_data->kind], *addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004098 sio_data->sioreg = sioaddr;
4099
4100 return 0;
4101}
4102
4103/*
4104 * when Super-I/O functions move to a separate file, the Super-I/O
4105 * bus will manage the lifetime of the device and this module will only keep
4106 * track of the nct6775 driver. But since we platform_device_alloc(), we
4107 * must keep track of the device
4108 */
4109static struct platform_device *pdev;
4110
4111static int __init sensors_nct6775_init(void)
4112{
4113 int err;
4114 unsigned short address;
4115 struct resource res;
4116 struct nct6775_sio_data sio_data;
4117
4118 /*
4119 * initialize sio_data->kind and sio_data->sioreg.
4120 *
4121 * when Super-I/O functions move to a separate file, the Super-I/O
4122 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4123 * nct6775 hardware monitor, and call probe()
4124 */
4125 if (nct6775_find(0x2e, &address, &sio_data) &&
4126 nct6775_find(0x4e, &address, &sio_data))
4127 return -ENODEV;
4128
4129 err = platform_driver_register(&nct6775_driver);
4130 if (err)
4131 goto exit;
4132
4133 pdev = platform_device_alloc(DRVNAME, address);
4134 if (!pdev) {
4135 err = -ENOMEM;
4136 pr_err("Device allocation failed\n");
4137 goto exit_unregister;
4138 }
4139
4140 err = platform_device_add_data(pdev, &sio_data,
4141 sizeof(struct nct6775_sio_data));
4142 if (err) {
4143 pr_err("Platform data allocation failed\n");
4144 goto exit_device_put;
4145 }
4146
4147 memset(&res, 0, sizeof(res));
4148 res.name = DRVNAME;
4149 res.start = address + IOREGION_OFFSET;
4150 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4151 res.flags = IORESOURCE_IO;
4152
4153 err = acpi_check_resource_conflict(&res);
4154 if (err)
4155 goto exit_device_put;
4156
4157 err = platform_device_add_resources(pdev, &res, 1);
4158 if (err) {
4159 pr_err("Device resource addition failed (%d)\n", err);
4160 goto exit_device_put;
4161 }
4162
4163 /* platform_device_add calls probe() */
4164 err = platform_device_add(pdev);
4165 if (err) {
4166 pr_err("Device addition failed (%d)\n", err);
4167 goto exit_device_put;
4168 }
4169
4170 return 0;
4171
4172exit_device_put:
4173 platform_device_put(pdev);
4174exit_unregister:
4175 platform_driver_unregister(&nct6775_driver);
4176exit:
4177 return err;
4178}
4179
4180static void __exit sensors_nct6775_exit(void)
4181{
4182 platform_device_unregister(pdev);
4183 platform_driver_unregister(&nct6775_driver);
4184}
4185
4186MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4187MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4188MODULE_LICENSE("GPL");
4189
4190module_init(sensors_nct6775_init);
4191module_exit(sensors_nct6775_exit);