blob: 6d5859718113c1d055b93114cde261372cd7849d [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;
557 struct mutex lock;
558
Guenter Roeckaa136e52012-12-04 03:26:05 -0800559 u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
560 * 3=temp_crit
561 */
562 u8 temp_src[NUM_TEMP];
563 u16 reg_temp_config[NUM_TEMP];
564 const char * const *temp_label;
565 int temp_label_num;
566
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700567 u16 REG_CONFIG;
568 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800569 u16 REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700570
571 const s8 *ALARM_BITS;
572
573 const u16 *REG_VIN;
574 const u16 *REG_IN_MINMAX[2];
575
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800576 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800577 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800578 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800579 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800580 const u16 *REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800581 const u16 *REG_FAN_TIME[3];
582
583 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800584
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800585 const u8 *REG_PWM_MODE;
586 const u8 *PWM_MODE_MASK;
587
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800588 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
589 * [3]=pwm_max, [4]=pwm_step,
590 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800591 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800592 const u16 *REG_PWM_READ;
593
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800594 const u16 *REG_AUTO_TEMP;
595 const u16 *REG_AUTO_PWM;
596
597 const u16 *REG_CRITICAL_TEMP;
598 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
599
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800600 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800601 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800602 const u16 *REG_WEIGHT_TEMP_SEL;
603 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
604
Guenter Roeckaa136e52012-12-04 03:26:05 -0800605 const u16 *REG_TEMP_OFFSET;
606
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700607 const u16 *REG_ALARM;
608
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800609 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
610 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
611
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700612 struct mutex update_lock;
613 bool valid; /* true if following fields are valid */
614 unsigned long last_updated; /* In jiffies */
615
616 /* Register values */
617 u8 bank; /* current register bank */
618 u8 in_num; /* number of in inputs we have */
619 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800620 unsigned int rpm[5];
621 u16 fan_min[5];
Guenter Roeck5c25d952012-12-11 07:29:06 -0800622 u8 fan_pulses[5];
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800623 u8 fan_div[5];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800624 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800625 u8 has_fan; /* some fan inputs can be disabled */
626 u8 has_fan_min; /* some fans don't have min register */
627 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700628
Guenter Roeckaa136e52012-12-04 03:26:05 -0800629 u8 temp_fixed_num; /* 3 or 6 */
630 u8 temp_type[NUM_TEMP_FIXED];
631 s8 temp_offset[NUM_TEMP_FIXED];
632 s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
633 * 3=temp_crit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700634 u64 alarms;
635
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800636 u8 pwm_num; /* number of pwm */
637 u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
638 enum pwm_enable pwm_enable[5];
639 /* 0->off
640 * 1->manual
641 * 2->thermal cruise mode (also called SmartFan I)
642 * 3->fan speed cruise mode
643 * 4->SmartFan III
644 * 5->enhanced variable thermal cruise (SmartFan IV)
645 */
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800646 u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
647 * [3]=pwm_max, [4]=pwm_step,
648 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800649 */
650
651 u8 target_temp[5];
652 u8 target_temp_mask;
653 u32 target_speed[5];
654 u32 target_speed_tolerance[5];
655 u8 speed_tolerance_limit;
656
657 u8 temp_tolerance[2][5];
658 u8 tolerance_mask;
659
660 u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
661
662 /* Automatic fan speed control registers */
663 int auto_pwm_num;
664 u8 auto_pwm[5][7];
665 u8 auto_temp[5][7];
666 u8 pwm_temp_sel[5];
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800667 u8 pwm_weight_temp_sel[5];
668 u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol,
669 * 2->temp_base
670 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800671
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700672 u8 vid;
673 u8 vrm;
674
Guenter Roeckaa136e52012-12-04 03:26:05 -0800675 u16 have_temp;
676 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700677 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800678#ifdef CONFIG_PM
679 /* Remember extra register values over suspend/resume */
680 u8 vbat;
681 u8 fandiv1;
682 u8 fandiv2;
683#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700684};
685
686struct nct6775_sio_data {
687 int sioreg;
688 enum kinds kind;
689};
690
691static bool is_word_sized(struct nct6775_data *data, u16 reg)
692{
693 switch (data->kind) {
694 case nct6775:
695 return (((reg & 0xff00) == 0x100 ||
696 (reg & 0xff00) == 0x200) &&
697 ((reg & 0x00ff) == 0x50 ||
698 (reg & 0x00ff) == 0x53 ||
699 (reg & 0x00ff) == 0x55)) ||
700 (reg & 0xfff0) == 0x630 ||
701 reg == 0x640 || reg == 0x642 ||
702 reg == 0x662 ||
703 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
704 reg == 0x73 || reg == 0x75 || reg == 0x77;
705 case nct6776:
706 return (((reg & 0xff00) == 0x100 ||
707 (reg & 0xff00) == 0x200) &&
708 ((reg & 0x00ff) == 0x50 ||
709 (reg & 0x00ff) == 0x53 ||
710 (reg & 0x00ff) == 0x55)) ||
711 (reg & 0xfff0) == 0x630 ||
712 reg == 0x402 ||
713 reg == 0x640 || reg == 0x642 ||
714 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
715 reg == 0x73 || reg == 0x75 || reg == 0x77;
716 case nct6779:
717 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
718 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
719 reg == 0x402 ||
720 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
721 reg == 0x640 || reg == 0x642 ||
722 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
723 reg == 0x7b;
724 }
725 return false;
726}
727
728/*
729 * On older chips, only registers 0x50-0x5f are banked.
730 * On more recent chips, all registers are banked.
731 * Assume that is the case and set the bank number for each access.
732 * Cache the bank number so it only needs to be set if it changes.
733 */
734static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
735{
736 u8 bank = reg >> 8;
737 if (data->bank != bank) {
738 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
739 outb_p(bank, data->addr + DATA_REG_OFFSET);
740 data->bank = bank;
741 }
742}
743
744static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
745{
746 int res, word_sized = is_word_sized(data, reg);
747
748 mutex_lock(&data->lock);
749
750 nct6775_set_bank(data, reg);
751 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
752 res = inb_p(data->addr + DATA_REG_OFFSET);
753 if (word_sized) {
754 outb_p((reg & 0xff) + 1,
755 data->addr + ADDR_REG_OFFSET);
756 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
757 }
758
759 mutex_unlock(&data->lock);
760 return res;
761}
762
763static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
764{
765 int word_sized = is_word_sized(data, reg);
766
767 mutex_lock(&data->lock);
768
769 nct6775_set_bank(data, reg);
770 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
771 if (word_sized) {
772 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
773 outb_p((reg & 0xff) + 1,
774 data->addr + ADDR_REG_OFFSET);
775 }
776 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
777
778 mutex_unlock(&data->lock);
779 return 0;
780}
781
Guenter Roeckaa136e52012-12-04 03:26:05 -0800782/* We left-align 8-bit temperature values to make the code simpler */
783static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
784{
785 u16 res;
786
787 res = nct6775_read_value(data, reg);
788 if (!is_word_sized(data, reg))
789 res <<= 8;
790
791 return res;
792}
793
794static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
795{
796 if (!is_word_sized(data, reg))
797 value >>= 8;
798 return nct6775_write_value(data, reg, value);
799}
800
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800801/* This function assumes that the caller holds data->update_lock */
802static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
803{
804 u8 reg;
805
806 switch (nr) {
807 case 0:
808 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
809 | (data->fan_div[0] & 0x7);
810 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
811 break;
812 case 1:
813 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
814 | ((data->fan_div[1] << 4) & 0x70);
815 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
816 break;
817 case 2:
818 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
819 | (data->fan_div[2] & 0x7);
820 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
821 break;
822 case 3:
823 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
824 | ((data->fan_div[3] << 4) & 0x70);
825 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
826 break;
827 }
828}
829
830static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
831{
832 if (data->kind == nct6775)
833 nct6775_write_fan_div(data, nr);
834}
835
836static void nct6775_update_fan_div(struct nct6775_data *data)
837{
838 u8 i;
839
840 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
841 data->fan_div[0] = i & 0x7;
842 data->fan_div[1] = (i & 0x70) >> 4;
843 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
844 data->fan_div[2] = i & 0x7;
845 if (data->has_fan & (1<<3))
846 data->fan_div[3] = (i & 0x70) >> 4;
847}
848
849static void nct6775_update_fan_div_common(struct nct6775_data *data)
850{
851 if (data->kind == nct6775)
852 nct6775_update_fan_div(data);
853}
854
855static void nct6775_init_fan_div(struct nct6775_data *data)
856{
857 int i;
858
859 nct6775_update_fan_div_common(data);
860 /*
861 * For all fans, start with highest divider value if the divider
862 * register is not initialized. This ensures that we get a
863 * reading from the fan count register, even if it is not optimal.
864 * We'll compute a better divider later on.
865 */
866 for (i = 0; i < 3; i++) {
867 if (!(data->has_fan & (1 << i)))
868 continue;
869 if (data->fan_div[i] == 0) {
870 data->fan_div[i] = 7;
871 nct6775_write_fan_div_common(data, i);
872 }
873 }
874}
875
876static void nct6775_init_fan_common(struct device *dev,
877 struct nct6775_data *data)
878{
879 int i;
880 u8 reg;
881
882 if (data->has_fan_div)
883 nct6775_init_fan_div(data);
884
885 /*
886 * If fan_min is not set (0), set it to 0xff to disable it. This
887 * prevents the unnecessary warning when fanX_min is reported as 0.
888 */
889 for (i = 0; i < 5; i++) {
890 if (data->has_fan_min & (1 << i)) {
891 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
892 if (!reg)
893 nct6775_write_value(data, data->REG_FAN_MIN[i],
894 data->has_fan_div ? 0xff
895 : 0xff1f);
896 }
897 }
898}
899
900static void nct6775_select_fan_div(struct device *dev,
901 struct nct6775_data *data, int nr, u16 reg)
902{
903 u8 fan_div = data->fan_div[nr];
904 u16 fan_min;
905
906 if (!data->has_fan_div)
907 return;
908
909 /*
910 * If we failed to measure the fan speed, or the reported value is not
911 * in the optimal range, and the clock divider can be modified,
912 * let's try that for next time.
913 */
914 if (reg == 0x00 && fan_div < 0x07)
915 fan_div++;
916 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
917 fan_div--;
918
919 if (fan_div != data->fan_div[nr]) {
920 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
921 nr + 1, div_from_reg(data->fan_div[nr]),
922 div_from_reg(fan_div));
923
924 /* Preserve min limit if possible */
925 if (data->has_fan_min & (1 << nr)) {
926 fan_min = data->fan_min[nr];
927 if (fan_div > data->fan_div[nr]) {
928 if (fan_min != 255 && fan_min > 1)
929 fan_min >>= 1;
930 } else {
931 if (fan_min != 255) {
932 fan_min <<= 1;
933 if (fan_min > 254)
934 fan_min = 254;
935 }
936 }
937 if (fan_min != data->fan_min[nr]) {
938 data->fan_min[nr] = fan_min;
939 nct6775_write_value(data, data->REG_FAN_MIN[nr],
940 fan_min);
941 }
942 }
943 data->fan_div[nr] = fan_div;
944 nct6775_write_fan_div_common(data, nr);
945 }
946}
947
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800948static void nct6775_update_pwm(struct device *dev)
949{
950 struct nct6775_data *data = dev_get_drvdata(dev);
951 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800952 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800953 bool duty_is_dc;
954
955 for (i = 0; i < data->pwm_num; i++) {
956 if (!(data->has_pwm & (1 << i)))
957 continue;
958
959 duty_is_dc = data->REG_PWM_MODE[i] &&
960 (nct6775_read_value(data, data->REG_PWM_MODE[i])
961 & data->PWM_MODE_MASK[i]);
962 data->pwm_mode[i] = duty_is_dc;
963
964 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
965 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
966 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
967 data->pwm[j][i]
968 = nct6775_read_value(data,
969 data->REG_PWM[j][i]);
970 }
971 }
972
973 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
974 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800975
976 if (!data->temp_tolerance[0][i] ||
977 data->pwm_enable[i] != speed_cruise)
978 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
979 if (!data->target_speed_tolerance[i] ||
980 data->pwm_enable[i] == speed_cruise) {
981 u8 t = fanmodecfg & 0x0f;
982 if (data->REG_TOLERANCE_H) {
983 t |= (nct6775_read_value(data,
984 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
985 }
986 data->target_speed_tolerance[i] = t;
987 }
988
989 data->temp_tolerance[1][i] =
990 nct6775_read_value(data,
991 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
992
993 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
994 data->pwm_temp_sel[i] = reg & 0x1f;
995 /* If fan can stop, report floor as 0 */
996 if (reg & 0x80)
997 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800998
999 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1000 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1001 /* If weight is disabled, report weight source as 0 */
1002 if (j == 1 && !(reg & 0x80))
1003 data->pwm_weight_temp_sel[i] = 0;
1004
1005 /* Weight temp data */
1006 for (j = 0; j < 3; j++) {
1007 data->weight_temp[j][i]
1008 = nct6775_read_value(data,
1009 data->REG_WEIGHT_TEMP[j][i]);
1010 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001011 }
1012}
1013
1014static void nct6775_update_pwm_limits(struct device *dev)
1015{
1016 struct nct6775_data *data = dev_get_drvdata(dev);
1017 int i, j;
1018 u8 reg;
1019 u16 reg_t;
1020
1021 for (i = 0; i < data->pwm_num; i++) {
1022 if (!(data->has_pwm & (1 << i)))
1023 continue;
1024
1025 for (j = 0; j < 3; j++) {
1026 data->fan_time[j][i] =
1027 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1028 }
1029
1030 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1031 /* Update only in matching mode or if never updated */
1032 if (!data->target_temp[i] ||
1033 data->pwm_enable[i] == thermal_cruise)
1034 data->target_temp[i] = reg_t & data->target_temp_mask;
1035 if (!data->target_speed[i] ||
1036 data->pwm_enable[i] == speed_cruise) {
1037 if (data->REG_TOLERANCE_H) {
1038 reg_t |= (nct6775_read_value(data,
1039 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1040 }
1041 data->target_speed[i] = reg_t;
1042 }
1043
1044 for (j = 0; j < data->auto_pwm_num; j++) {
1045 data->auto_pwm[i][j] =
1046 nct6775_read_value(data,
1047 NCT6775_AUTO_PWM(data, i, j));
1048 data->auto_temp[i][j] =
1049 nct6775_read_value(data,
1050 NCT6775_AUTO_TEMP(data, i, j));
1051 }
1052
1053 /* critical auto_pwm temperature data */
1054 data->auto_temp[i][data->auto_pwm_num] =
1055 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1056
1057 switch (data->kind) {
1058 case nct6775:
1059 reg = nct6775_read_value(data,
1060 NCT6775_REG_CRITICAL_ENAB[i]);
1061 data->auto_pwm[i][data->auto_pwm_num] =
1062 (reg & 0x02) ? 0xff : 0x00;
1063 break;
1064 case nct6776:
1065 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1066 break;
1067 case nct6779:
1068 reg = nct6775_read_value(data,
1069 NCT6779_REG_CRITICAL_PWM_ENABLE[i]);
1070 if (reg & 1)
1071 data->auto_pwm[i][data->auto_pwm_num] =
1072 nct6775_read_value(data,
1073 NCT6779_REG_CRITICAL_PWM[i]);
1074 else
1075 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1076 break;
1077 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001078 }
1079}
1080
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001081static struct nct6775_data *nct6775_update_device(struct device *dev)
1082{
1083 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001084 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001085
1086 mutex_lock(&data->update_lock);
1087
1088 if (time_after(jiffies, data->last_updated + HZ + HZ/2)
1089 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001090 /* Fan clock dividers */
1091 nct6775_update_fan_div_common(data);
1092
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001093 /* Measured voltages and limits */
1094 for (i = 0; i < data->in_num; i++) {
1095 if (!(data->have_in & (1 << i)))
1096 continue;
1097
1098 data->in[i][0] = nct6775_read_value(data,
1099 data->REG_VIN[i]);
1100 data->in[i][1] = nct6775_read_value(data,
1101 data->REG_IN_MINMAX[0][i]);
1102 data->in[i][2] = nct6775_read_value(data,
1103 data->REG_IN_MINMAX[1][i]);
1104 }
1105
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001106 /* Measured fan speeds and limits */
1107 for (i = 0; i < 5; i++) {
1108 u16 reg;
1109
1110 if (!(data->has_fan & (1 << i)))
1111 continue;
1112
1113 reg = nct6775_read_value(data, data->REG_FAN[i]);
1114 data->rpm[i] = data->fan_from_reg(reg,
1115 data->fan_div[i]);
1116
1117 if (data->has_fan_min & (1 << i))
1118 data->fan_min[i] = nct6775_read_value(data,
1119 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001120 data->fan_pulses[i] =
1121 nct6775_read_value(data, data->REG_FAN_PULSES[i]);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001122
1123 nct6775_select_fan_div(dev, data, i, reg);
1124 }
1125
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001126 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001127 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001128
Guenter Roeckaa136e52012-12-04 03:26:05 -08001129 /* Measured temperatures and limits */
1130 for (i = 0; i < NUM_TEMP; i++) {
1131 if (!(data->have_temp & (1 << i)))
1132 continue;
1133 for (j = 0; j < 4; j++) {
1134 if (data->reg_temp[j][i])
1135 data->temp[j][i]
1136 = nct6775_read_temp(data,
1137 data->reg_temp[j][i]);
1138 }
1139 if (!(data->have_temp_fixed & (1 << i)))
1140 continue;
1141 data->temp_offset[i]
1142 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1143 }
1144
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001145 data->alarms = 0;
1146 for (i = 0; i < NUM_REG_ALARM; i++) {
1147 u8 alarm;
1148 if (!data->REG_ALARM[i])
1149 continue;
1150 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1151 data->alarms |= ((u64)alarm) << (i << 3);
1152 }
1153
1154 data->last_updated = jiffies;
1155 data->valid = true;
1156 }
1157
1158 mutex_unlock(&data->update_lock);
1159 return data;
1160}
1161
1162/*
1163 * Sysfs callback functions
1164 */
1165static ssize_t
1166show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1167{
1168 struct nct6775_data *data = nct6775_update_device(dev);
1169 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1170 int nr = sattr->nr;
1171 int index = sattr->index;
1172 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1173}
1174
1175static ssize_t
1176store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1177 size_t count)
1178{
1179 struct nct6775_data *data = dev_get_drvdata(dev);
1180 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1181 int nr = sattr->nr;
1182 int index = sattr->index;
1183 unsigned long val;
1184 int err = kstrtoul(buf, 10, &val);
1185 if (err < 0)
1186 return err;
1187 mutex_lock(&data->update_lock);
1188 data->in[nr][index] = in_to_reg(val, nr);
1189 nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr],
1190 data->in[nr][index]);
1191 mutex_unlock(&data->update_lock);
1192 return count;
1193}
1194
1195static ssize_t
1196show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1197{
1198 struct nct6775_data *data = nct6775_update_device(dev);
1199 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1200 int nr = data->ALARM_BITS[sattr->index];
1201 return sprintf(buf, "%u\n",
1202 (unsigned int)((data->alarms >> nr) & 0x01));
1203}
1204
1205static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
1206static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
1207static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
1208static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0);
1209static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0);
1210static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0);
1211static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0);
1212static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0);
1213static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0);
1214static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0);
1215static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0);
1216static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0);
1217static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0);
1218static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0);
1219static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0);
1220
1221static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
1222static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
1223static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
1224static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
1225static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
1226static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
1227static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
1228static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
1229static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
1230static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
1231static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
1232static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11);
1233static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12);
1234static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13);
1235static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14);
1236
1237static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg,
1238 store_in_reg, 0, 1);
1239static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg,
1240 store_in_reg, 1, 1);
1241static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg,
1242 store_in_reg, 2, 1);
1243static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg,
1244 store_in_reg, 3, 1);
1245static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg,
1246 store_in_reg, 4, 1);
1247static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg,
1248 store_in_reg, 5, 1);
1249static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg,
1250 store_in_reg, 6, 1);
1251static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg,
1252 store_in_reg, 7, 1);
1253static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg,
1254 store_in_reg, 8, 1);
1255static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg,
1256 store_in_reg, 9, 1);
1257static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg,
1258 store_in_reg, 10, 1);
1259static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg,
1260 store_in_reg, 11, 1);
1261static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg,
1262 store_in_reg, 12, 1);
1263static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg,
1264 store_in_reg, 13, 1);
1265static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg,
1266 store_in_reg, 14, 1);
1267
1268static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg,
1269 store_in_reg, 0, 2);
1270static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg,
1271 store_in_reg, 1, 2);
1272static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg,
1273 store_in_reg, 2, 2);
1274static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg,
1275 store_in_reg, 3, 2);
1276static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg,
1277 store_in_reg, 4, 2);
1278static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg,
1279 store_in_reg, 5, 2);
1280static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg,
1281 store_in_reg, 6, 2);
1282static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg,
1283 store_in_reg, 7, 2);
1284static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg,
1285 store_in_reg, 8, 2);
1286static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg,
1287 store_in_reg, 9, 2);
1288static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg,
1289 store_in_reg, 10, 2);
1290static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg,
1291 store_in_reg, 11, 2);
1292static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg,
1293 store_in_reg, 12, 2);
1294static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg,
1295 store_in_reg, 13, 2);
1296static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg,
1297 store_in_reg, 14, 2);
1298
1299static struct attribute *nct6775_attributes_in[15][5] = {
1300 {
1301 &sensor_dev_attr_in0_input.dev_attr.attr,
1302 &sensor_dev_attr_in0_min.dev_attr.attr,
1303 &sensor_dev_attr_in0_max.dev_attr.attr,
1304 &sensor_dev_attr_in0_alarm.dev_attr.attr,
1305 NULL
1306 },
1307 {
1308 &sensor_dev_attr_in1_input.dev_attr.attr,
1309 &sensor_dev_attr_in1_min.dev_attr.attr,
1310 &sensor_dev_attr_in1_max.dev_attr.attr,
1311 &sensor_dev_attr_in1_alarm.dev_attr.attr,
1312 NULL
1313 },
1314 {
1315 &sensor_dev_attr_in2_input.dev_attr.attr,
1316 &sensor_dev_attr_in2_min.dev_attr.attr,
1317 &sensor_dev_attr_in2_max.dev_attr.attr,
1318 &sensor_dev_attr_in2_alarm.dev_attr.attr,
1319 NULL
1320 },
1321 {
1322 &sensor_dev_attr_in3_input.dev_attr.attr,
1323 &sensor_dev_attr_in3_min.dev_attr.attr,
1324 &sensor_dev_attr_in3_max.dev_attr.attr,
1325 &sensor_dev_attr_in3_alarm.dev_attr.attr,
1326 NULL
1327 },
1328 {
1329 &sensor_dev_attr_in4_input.dev_attr.attr,
1330 &sensor_dev_attr_in4_min.dev_attr.attr,
1331 &sensor_dev_attr_in4_max.dev_attr.attr,
1332 &sensor_dev_attr_in4_alarm.dev_attr.attr,
1333 NULL
1334 },
1335 {
1336 &sensor_dev_attr_in5_input.dev_attr.attr,
1337 &sensor_dev_attr_in5_min.dev_attr.attr,
1338 &sensor_dev_attr_in5_max.dev_attr.attr,
1339 &sensor_dev_attr_in5_alarm.dev_attr.attr,
1340 NULL
1341 },
1342 {
1343 &sensor_dev_attr_in6_input.dev_attr.attr,
1344 &sensor_dev_attr_in6_min.dev_attr.attr,
1345 &sensor_dev_attr_in6_max.dev_attr.attr,
1346 &sensor_dev_attr_in6_alarm.dev_attr.attr,
1347 NULL
1348 },
1349 {
1350 &sensor_dev_attr_in7_input.dev_attr.attr,
1351 &sensor_dev_attr_in7_min.dev_attr.attr,
1352 &sensor_dev_attr_in7_max.dev_attr.attr,
1353 &sensor_dev_attr_in7_alarm.dev_attr.attr,
1354 NULL
1355 },
1356 {
1357 &sensor_dev_attr_in8_input.dev_attr.attr,
1358 &sensor_dev_attr_in8_min.dev_attr.attr,
1359 &sensor_dev_attr_in8_max.dev_attr.attr,
1360 &sensor_dev_attr_in8_alarm.dev_attr.attr,
1361 NULL
1362 },
1363 {
1364 &sensor_dev_attr_in9_input.dev_attr.attr,
1365 &sensor_dev_attr_in9_min.dev_attr.attr,
1366 &sensor_dev_attr_in9_max.dev_attr.attr,
1367 &sensor_dev_attr_in9_alarm.dev_attr.attr,
1368 NULL
1369 },
1370 {
1371 &sensor_dev_attr_in10_input.dev_attr.attr,
1372 &sensor_dev_attr_in10_min.dev_attr.attr,
1373 &sensor_dev_attr_in10_max.dev_attr.attr,
1374 &sensor_dev_attr_in10_alarm.dev_attr.attr,
1375 NULL
1376 },
1377 {
1378 &sensor_dev_attr_in11_input.dev_attr.attr,
1379 &sensor_dev_attr_in11_min.dev_attr.attr,
1380 &sensor_dev_attr_in11_max.dev_attr.attr,
1381 &sensor_dev_attr_in11_alarm.dev_attr.attr,
1382 NULL
1383 },
1384 {
1385 &sensor_dev_attr_in12_input.dev_attr.attr,
1386 &sensor_dev_attr_in12_min.dev_attr.attr,
1387 &sensor_dev_attr_in12_max.dev_attr.attr,
1388 &sensor_dev_attr_in12_alarm.dev_attr.attr,
1389 NULL
1390 },
1391 {
1392 &sensor_dev_attr_in13_input.dev_attr.attr,
1393 &sensor_dev_attr_in13_min.dev_attr.attr,
1394 &sensor_dev_attr_in13_max.dev_attr.attr,
1395 &sensor_dev_attr_in13_alarm.dev_attr.attr,
1396 NULL
1397 },
1398 {
1399 &sensor_dev_attr_in14_input.dev_attr.attr,
1400 &sensor_dev_attr_in14_min.dev_attr.attr,
1401 &sensor_dev_attr_in14_max.dev_attr.attr,
1402 &sensor_dev_attr_in14_alarm.dev_attr.attr,
1403 NULL
1404 },
1405};
1406
1407static const struct attribute_group nct6775_group_in[15] = {
1408 { .attrs = nct6775_attributes_in[0] },
1409 { .attrs = nct6775_attributes_in[1] },
1410 { .attrs = nct6775_attributes_in[2] },
1411 { .attrs = nct6775_attributes_in[3] },
1412 { .attrs = nct6775_attributes_in[4] },
1413 { .attrs = nct6775_attributes_in[5] },
1414 { .attrs = nct6775_attributes_in[6] },
1415 { .attrs = nct6775_attributes_in[7] },
1416 { .attrs = nct6775_attributes_in[8] },
1417 { .attrs = nct6775_attributes_in[9] },
1418 { .attrs = nct6775_attributes_in[10] },
1419 { .attrs = nct6775_attributes_in[11] },
1420 { .attrs = nct6775_attributes_in[12] },
1421 { .attrs = nct6775_attributes_in[13] },
1422 { .attrs = nct6775_attributes_in[14] },
1423};
1424
1425static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001426show_fan(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", data->rpm[nr]);
1432}
1433
1434static ssize_t
1435show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1436{
1437 struct nct6775_data *data = nct6775_update_device(dev);
1438 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1439 int nr = sattr->index;
1440 return sprintf(buf, "%d\n",
1441 data->fan_from_reg_min(data->fan_min[nr],
1442 data->fan_div[nr]));
1443}
1444
1445static ssize_t
1446show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1447{
1448 struct nct6775_data *data = nct6775_update_device(dev);
1449 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1450 int nr = sattr->index;
1451 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1452}
1453
1454static ssize_t
1455store_fan_min(struct device *dev, struct device_attribute *attr,
1456 const char *buf, size_t count)
1457{
1458 struct nct6775_data *data = dev_get_drvdata(dev);
1459 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1460 int nr = sattr->index;
1461 unsigned long val;
1462 int err;
1463 unsigned int reg;
1464 u8 new_div;
1465
1466 err = kstrtoul(buf, 10, &val);
1467 if (err < 0)
1468 return err;
1469
1470 mutex_lock(&data->update_lock);
1471 if (!data->has_fan_div) {
1472 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1473 if (!val) {
1474 val = 0xff1f;
1475 } else {
1476 if (val > 1350000U)
1477 val = 135000U;
1478 val = 1350000U / val;
1479 val = (val & 0x1f) | ((val << 3) & 0xff00);
1480 }
1481 data->fan_min[nr] = val;
1482 goto write_min; /* Leave fan divider alone */
1483 }
1484 if (!val) {
1485 /* No min limit, alarm disabled */
1486 data->fan_min[nr] = 255;
1487 new_div = data->fan_div[nr]; /* No change */
1488 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1489 goto write_div;
1490 }
1491 reg = 1350000U / val;
1492 if (reg >= 128 * 255) {
1493 /*
1494 * Speed below this value cannot possibly be represented,
1495 * even with the highest divider (128)
1496 */
1497 data->fan_min[nr] = 254;
1498 new_div = 7; /* 128 == (1 << 7) */
1499 dev_warn(dev,
1500 "fan%u low limit %lu below minimum %u, set to minimum\n",
1501 nr + 1, val, data->fan_from_reg_min(254, 7));
1502 } else if (!reg) {
1503 /*
1504 * Speed above this value cannot possibly be represented,
1505 * even with the lowest divider (1)
1506 */
1507 data->fan_min[nr] = 1;
1508 new_div = 0; /* 1 == (1 << 0) */
1509 dev_warn(dev,
1510 "fan%u low limit %lu above maximum %u, set to maximum\n",
1511 nr + 1, val, data->fan_from_reg_min(1, 0));
1512 } else {
1513 /*
1514 * Automatically pick the best divider, i.e. the one such
1515 * that the min limit will correspond to a register value
1516 * in the 96..192 range
1517 */
1518 new_div = 0;
1519 while (reg > 192 && new_div < 7) {
1520 reg >>= 1;
1521 new_div++;
1522 }
1523 data->fan_min[nr] = reg;
1524 }
1525
1526write_div:
1527 /*
1528 * Write both the fan clock divider (if it changed) and the new
1529 * fan min (unconditionally)
1530 */
1531 if (new_div != data->fan_div[nr]) {
1532 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1533 nr + 1, div_from_reg(data->fan_div[nr]),
1534 div_from_reg(new_div));
1535 data->fan_div[nr] = new_div;
1536 nct6775_write_fan_div_common(data, nr);
1537 /* Give the chip time to sample a new speed value */
1538 data->last_updated = jiffies;
1539 }
1540
1541write_min:
1542 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1543 mutex_unlock(&data->update_lock);
1544
1545 return count;
1546}
1547
Guenter Roeck5c25d952012-12-11 07:29:06 -08001548static ssize_t
1549show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1550{
1551 struct nct6775_data *data = nct6775_update_device(dev);
1552 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1553 int p = data->fan_pulses[sattr->index];
1554
1555 return sprintf(buf, "%d\n", p ? : 4);
1556}
1557
1558static ssize_t
1559store_fan_pulses(struct device *dev, struct device_attribute *attr,
1560 const char *buf, size_t count)
1561{
1562 struct nct6775_data *data = dev_get_drvdata(dev);
1563 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1564 int nr = sattr->index;
1565 unsigned long val;
1566 int err;
1567
1568 err = kstrtoul(buf, 10, &val);
1569 if (err < 0)
1570 return err;
1571
1572 if (val > 4)
1573 return -EINVAL;
1574
1575 mutex_lock(&data->update_lock);
1576 data->fan_pulses[nr] = val & 3;
1577 nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3);
1578 mutex_unlock(&data->update_lock);
1579
1580 return count;
1581}
1582
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001583static struct sensor_device_attribute sda_fan_input[] = {
1584 SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
1585 SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
1586 SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
1587 SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
1588 SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
1589};
1590
1591static struct sensor_device_attribute sda_fan_alarm[] = {
1592 SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE),
1593 SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1),
1594 SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2),
1595 SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3),
1596 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4),
1597};
1598
1599static struct sensor_device_attribute sda_fan_min[] = {
1600 SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
1601 store_fan_min, 0),
1602 SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
1603 store_fan_min, 1),
1604 SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
1605 store_fan_min, 2),
1606 SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
1607 store_fan_min, 3),
1608 SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
1609 store_fan_min, 4),
1610};
1611
Guenter Roeck5c25d952012-12-11 07:29:06 -08001612static struct sensor_device_attribute sda_fan_pulses[] = {
1613 SENSOR_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1614 store_fan_pulses, 0),
1615 SENSOR_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1616 store_fan_pulses, 1),
1617 SENSOR_ATTR(fan3_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1618 store_fan_pulses, 2),
1619 SENSOR_ATTR(fan4_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1620 store_fan_pulses, 3),
1621 SENSOR_ATTR(fan5_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
1622 store_fan_pulses, 4),
1623};
1624
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001625static struct sensor_device_attribute sda_fan_div[] = {
1626 SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
1627 SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
1628 SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
1629 SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
1630 SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
1631};
1632
1633static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001634show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1635{
1636 struct nct6775_data *data = nct6775_update_device(dev);
1637 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1638 int nr = sattr->index;
1639 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1640}
1641
1642static ssize_t
1643show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1644{
1645 struct nct6775_data *data = nct6775_update_device(dev);
1646 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1647 int nr = sattr->nr;
1648 int index = sattr->index;
1649
1650 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1651}
1652
1653static ssize_t
1654store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1655 size_t count)
1656{
1657 struct nct6775_data *data = dev_get_drvdata(dev);
1658 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1659 int nr = sattr->nr;
1660 int index = sattr->index;
1661 int err;
1662 long val;
1663
1664 err = kstrtol(buf, 10, &val);
1665 if (err < 0)
1666 return err;
1667
1668 mutex_lock(&data->update_lock);
1669 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1670 nct6775_write_temp(data, data->reg_temp[index][nr],
1671 data->temp[index][nr]);
1672 mutex_unlock(&data->update_lock);
1673 return count;
1674}
1675
1676static ssize_t
1677show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1678{
1679 struct nct6775_data *data = nct6775_update_device(dev);
1680 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1681
1682 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1683}
1684
1685static ssize_t
1686store_temp_offset(struct device *dev, struct device_attribute *attr,
1687 const char *buf, size_t count)
1688{
1689 struct nct6775_data *data = dev_get_drvdata(dev);
1690 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1691 int nr = sattr->index;
1692 long val;
1693 int err;
1694
1695 err = kstrtol(buf, 10, &val);
1696 if (err < 0)
1697 return err;
1698
1699 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1700
1701 mutex_lock(&data->update_lock);
1702 data->temp_offset[nr] = val;
1703 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1704 mutex_unlock(&data->update_lock);
1705
1706 return count;
1707}
1708
1709static ssize_t
1710show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1711{
1712 struct nct6775_data *data = nct6775_update_device(dev);
1713 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1714 int nr = sattr->index;
1715 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
1716}
1717
1718static ssize_t
1719store_temp_type(struct device *dev, struct device_attribute *attr,
1720 const char *buf, size_t count)
1721{
1722 struct nct6775_data *data = nct6775_update_device(dev);
1723 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1724 int nr = sattr->index;
1725 unsigned long val;
1726 int err;
1727 u8 vbat, diode, bit;
1728
1729 err = kstrtoul(buf, 10, &val);
1730 if (err < 0)
1731 return err;
1732
1733 if (val != 1 && val != 3 && val != 4)
1734 return -EINVAL;
1735
1736 mutex_lock(&data->update_lock);
1737
1738 data->temp_type[nr] = val;
1739 vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr);
1740 diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr);
1741 bit = 0x02 << nr;
1742 switch (val) {
1743 case 1: /* CPU diode (diode, current mode) */
1744 vbat |= bit;
1745 diode |= bit;
1746 break;
1747 case 3: /* diode, voltage mode */
1748 vbat |= bit;
1749 break;
1750 case 4: /* thermistor */
1751 break;
1752 }
1753 nct6775_write_value(data, data->REG_VBAT, vbat);
1754 nct6775_write_value(data, data->REG_DIODE, diode);
1755
1756 mutex_unlock(&data->update_lock);
1757 return count;
1758}
1759
1760static struct sensor_device_attribute_2 sda_temp_input[] = {
1761 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
1762 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0),
1763 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0),
1764 SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0),
1765 SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0),
1766 SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0),
1767 SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0),
1768 SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0),
1769 SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0),
1770 SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0),
1771};
1772
1773static struct sensor_device_attribute sda_temp_label[] = {
1774 SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
1775 SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
1776 SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
1777 SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
1778 SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
1779 SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
1780 SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
1781 SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
1782 SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
1783 SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9),
1784};
1785
1786static struct sensor_device_attribute_2 sda_temp_max[] = {
1787 SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1788 0, 1),
1789 SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1790 1, 1),
1791 SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1792 2, 1),
1793 SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1794 3, 1),
1795 SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1796 4, 1),
1797 SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1798 5, 1),
1799 SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1800 6, 1),
1801 SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1802 7, 1),
1803 SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1804 8, 1),
1805 SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
1806 9, 1),
1807};
1808
1809static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
1810 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1811 0, 2),
1812 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1813 1, 2),
1814 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1815 2, 2),
1816 SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1817 3, 2),
1818 SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1819 4, 2),
1820 SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1821 5, 2),
1822 SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1823 6, 2),
1824 SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1825 7, 2),
1826 SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1827 8, 2),
1828 SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
1829 9, 2),
1830};
1831
1832static struct sensor_device_attribute_2 sda_temp_crit[] = {
1833 SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1834 0, 3),
1835 SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1836 1, 3),
1837 SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1838 2, 3),
1839 SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1840 3, 3),
1841 SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1842 4, 3),
1843 SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1844 5, 3),
1845 SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1846 6, 3),
1847 SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1848 7, 3),
1849 SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1850 8, 3),
1851 SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
1852 9, 3),
1853};
1854
1855static struct sensor_device_attribute sda_temp_offset[] = {
1856 SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1857 store_temp_offset, 0),
1858 SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1859 store_temp_offset, 1),
1860 SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1861 store_temp_offset, 2),
1862 SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1863 store_temp_offset, 3),
1864 SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1865 store_temp_offset, 4),
1866 SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset,
1867 store_temp_offset, 5),
1868};
1869
1870static struct sensor_device_attribute sda_temp_type[] = {
1871 SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
1872 store_temp_type, 0),
1873 SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
1874 store_temp_type, 1),
1875 SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
1876 store_temp_type, 2),
1877 SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type,
1878 store_temp_type, 3),
1879 SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type,
1880 store_temp_type, 4),
1881 SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type,
1882 store_temp_type, 5),
1883};
1884
1885static struct sensor_device_attribute sda_temp_alarm[] = {
1886 SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
1887 TEMP_ALARM_BASE),
1888 SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
1889 TEMP_ALARM_BASE + 1),
1890 SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
1891 TEMP_ALARM_BASE + 2),
1892 SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
1893 TEMP_ALARM_BASE + 3),
1894 SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
1895 TEMP_ALARM_BASE + 4),
1896 SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
1897 TEMP_ALARM_BASE + 5),
1898};
1899
1900#define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm)
1901
1902static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001903show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
1904{
1905 struct nct6775_data *data = nct6775_update_device(dev);
1906 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1907
1908 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
1909}
1910
1911static ssize_t
1912store_pwm_mode(struct device *dev, struct device_attribute *attr,
1913 const char *buf, size_t count)
1914{
1915 struct nct6775_data *data = dev_get_drvdata(dev);
1916 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1917 int nr = sattr->index;
1918 unsigned long val;
1919 int err;
1920 u8 reg;
1921
1922 err = kstrtoul(buf, 10, &val);
1923 if (err < 0)
1924 return err;
1925
1926 if (val > 1)
1927 return -EINVAL;
1928
1929 /* Setting DC mode is not supported for all chips/channels */
1930 if (data->REG_PWM_MODE[nr] == 0) {
1931 if (val)
1932 return -EINVAL;
1933 return count;
1934 }
1935
1936 mutex_lock(&data->update_lock);
1937 data->pwm_mode[nr] = val;
1938 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
1939 reg &= ~data->PWM_MODE_MASK[nr];
1940 if (val)
1941 reg |= data->PWM_MODE_MASK[nr];
1942 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
1943 mutex_unlock(&data->update_lock);
1944 return count;
1945}
1946
1947static ssize_t
1948show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
1949{
1950 struct nct6775_data *data = nct6775_update_device(dev);
1951 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1952 int nr = sattr->nr;
1953 int index = sattr->index;
1954 int pwm;
1955
1956 /*
1957 * For automatic fan control modes, show current pwm readings.
1958 * Otherwise, show the configured value.
1959 */
1960 if (index == 0 && data->pwm_enable[nr] > manual)
1961 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
1962 else
1963 pwm = data->pwm[index][nr];
1964
1965 return sprintf(buf, "%d\n", pwm);
1966}
1967
1968static ssize_t
1969store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
1970 size_t count)
1971{
1972 struct nct6775_data *data = dev_get_drvdata(dev);
1973 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1974 int nr = sattr->nr;
1975 int index = sattr->index;
1976 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001977 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
1978 int maxval[7]
1979 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001980 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001981 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001982
1983 err = kstrtoul(buf, 10, &val);
1984 if (err < 0)
1985 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001986 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001987
1988 mutex_lock(&data->update_lock);
1989 data->pwm[index][nr] = val;
1990 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001991 if (index == 2) { /* floor: disable if val == 0 */
1992 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
1993 reg &= 0x7f;
1994 if (val)
1995 reg |= 0x80;
1996 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
1997 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001998 mutex_unlock(&data->update_lock);
1999 return count;
2000}
2001
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002002/* Returns 0 if OK, -EINVAL otherwise */
2003static int check_trip_points(struct nct6775_data *data, int nr)
2004{
2005 int i;
2006
2007 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2008 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2009 return -EINVAL;
2010 }
2011 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2012 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2013 return -EINVAL;
2014 }
2015 /* validate critical temperature and pwm if enabled (pwm > 0) */
2016 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2017 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2018 data->auto_temp[nr][data->auto_pwm_num] ||
2019 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2020 data->auto_pwm[nr][data->auto_pwm_num])
2021 return -EINVAL;
2022 }
2023 return 0;
2024}
2025
2026static void pwm_update_registers(struct nct6775_data *data, int nr)
2027{
2028 u8 reg;
2029
2030 switch (data->pwm_enable[nr]) {
2031 case off:
2032 case manual:
2033 break;
2034 case speed_cruise:
2035 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2036 reg = (reg & ~data->tolerance_mask) |
2037 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2038 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2039 nct6775_write_value(data, data->REG_TARGET[nr],
2040 data->target_speed[nr] & 0xff);
2041 if (data->REG_TOLERANCE_H) {
2042 reg = (data->target_speed[nr] >> 8) & 0x0f;
2043 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2044 nct6775_write_value(data,
2045 data->REG_TOLERANCE_H[nr],
2046 reg);
2047 }
2048 break;
2049 case thermal_cruise:
2050 nct6775_write_value(data, data->REG_TARGET[nr],
2051 data->target_temp[nr]);
2052 /* intentional */
2053 default:
2054 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2055 reg = (reg & ~data->tolerance_mask) |
2056 data->temp_tolerance[0][nr];
2057 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2058 break;
2059 }
2060}
2061
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002062static ssize_t
2063show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2064{
2065 struct nct6775_data *data = nct6775_update_device(dev);
2066 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2067
2068 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2069}
2070
2071static ssize_t
2072store_pwm_enable(struct device *dev, struct device_attribute *attr,
2073 const char *buf, size_t count)
2074{
2075 struct nct6775_data *data = dev_get_drvdata(dev);
2076 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2077 int nr = sattr->index;
2078 unsigned long val;
2079 int err;
2080 u16 reg;
2081
2082 err = kstrtoul(buf, 10, &val);
2083 if (err < 0)
2084 return err;
2085
2086 if (val > sf4)
2087 return -EINVAL;
2088
2089 if (val == sf3 && data->kind != nct6775)
2090 return -EINVAL;
2091
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002092 if (val == sf4 && check_trip_points(data, nr)) {
2093 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2094 dev_err(dev, "Adjust trip points and try again\n");
2095 return -EINVAL;
2096 }
2097
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002098 mutex_lock(&data->update_lock);
2099 data->pwm_enable[nr] = val;
2100 if (val == off) {
2101 /*
2102 * turn off pwm control: select manual mode, set pwm to maximum
2103 */
2104 data->pwm[0][nr] = 255;
2105 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2106 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002107 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002108 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2109 reg &= 0x0f;
2110 reg |= pwm_enable_to_reg(val) << 4;
2111 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2112 mutex_unlock(&data->update_lock);
2113 return count;
2114}
2115
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002116static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002117show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002118{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002119 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002120
2121 for (i = 0; i < NUM_TEMP; i++) {
2122 if (!(data->have_temp & (1 << i)))
2123 continue;
2124 if (src == data->temp_src[i]) {
2125 sel = i + 1;
2126 break;
2127 }
2128 }
2129
2130 return sprintf(buf, "%d\n", sel);
2131}
2132
2133static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002134show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2135{
2136 struct nct6775_data *data = nct6775_update_device(dev);
2137 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2138 int index = sattr->index;
2139
2140 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2141}
2142
2143static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002144store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2145 const char *buf, size_t count)
2146{
2147 struct nct6775_data *data = nct6775_update_device(dev);
2148 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2149 int nr = sattr->index;
2150 unsigned long val;
2151 int err, reg, src;
2152
2153 err = kstrtoul(buf, 10, &val);
2154 if (err < 0)
2155 return err;
2156 if (val == 0 || val > NUM_TEMP)
2157 return -EINVAL;
2158 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2159 return -EINVAL;
2160
2161 mutex_lock(&data->update_lock);
2162 src = data->temp_src[val - 1];
2163 data->pwm_temp_sel[nr] = src;
2164 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2165 reg &= 0xe0;
2166 reg |= src;
2167 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2168 mutex_unlock(&data->update_lock);
2169
2170 return count;
2171}
2172
2173static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002174show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2175 char *buf)
2176{
2177 struct nct6775_data *data = nct6775_update_device(dev);
2178 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2179 int index = sattr->index;
2180
2181 return show_pwm_temp_sel_common(data, buf,
2182 data->pwm_weight_temp_sel[index]);
2183}
2184
2185static ssize_t
2186store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2187 const char *buf, size_t count)
2188{
2189 struct nct6775_data *data = nct6775_update_device(dev);
2190 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2191 int nr = sattr->index;
2192 unsigned long val;
2193 int err, reg, src;
2194
2195 err = kstrtoul(buf, 10, &val);
2196 if (err < 0)
2197 return err;
2198 if (val > NUM_TEMP)
2199 return -EINVAL;
2200 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2201 !data->temp_src[val - 1]))
2202 return -EINVAL;
2203
2204 mutex_lock(&data->update_lock);
2205 if (val) {
2206 src = data->temp_src[val - 1];
2207 data->pwm_weight_temp_sel[nr] = src;
2208 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2209 reg &= 0xe0;
2210 reg |= (src | 0x80);
2211 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2212 } else {
2213 data->pwm_weight_temp_sel[nr] = 0;
2214 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2215 reg &= 0x7f;
2216 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2217 }
2218 mutex_unlock(&data->update_lock);
2219
2220 return count;
2221}
2222
2223static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002224show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2225{
2226 struct nct6775_data *data = nct6775_update_device(dev);
2227 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2228
2229 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2230}
2231
2232static ssize_t
2233store_target_temp(struct device *dev, struct device_attribute *attr,
2234 const char *buf, size_t count)
2235{
2236 struct nct6775_data *data = dev_get_drvdata(dev);
2237 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2238 int nr = sattr->index;
2239 unsigned long val;
2240 int err;
2241
2242 err = kstrtoul(buf, 10, &val);
2243 if (err < 0)
2244 return err;
2245
2246 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2247 data->target_temp_mask);
2248
2249 mutex_lock(&data->update_lock);
2250 data->target_temp[nr] = val;
2251 pwm_update_registers(data, nr);
2252 mutex_unlock(&data->update_lock);
2253 return count;
2254}
2255
2256static ssize_t
2257show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2258{
2259 struct nct6775_data *data = nct6775_update_device(dev);
2260 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2261 int nr = sattr->index;
2262
2263 return sprintf(buf, "%d\n",
2264 fan_from_reg16(data->target_speed[nr],
2265 data->fan_div[nr]));
2266}
2267
2268static ssize_t
2269store_target_speed(struct device *dev, struct device_attribute *attr,
2270 const char *buf, size_t count)
2271{
2272 struct nct6775_data *data = dev_get_drvdata(dev);
2273 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2274 int nr = sattr->index;
2275 unsigned long val;
2276 int err;
2277 u16 speed;
2278
2279 err = kstrtoul(buf, 10, &val);
2280 if (err < 0)
2281 return err;
2282
2283 val = clamp_val(val, 0, 1350000U);
2284 speed = fan_to_reg(val, data->fan_div[nr]);
2285
2286 mutex_lock(&data->update_lock);
2287 data->target_speed[nr] = speed;
2288 pwm_update_registers(data, nr);
2289 mutex_unlock(&data->update_lock);
2290 return count;
2291}
2292
2293static ssize_t
2294show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2295 char *buf)
2296{
2297 struct nct6775_data *data = nct6775_update_device(dev);
2298 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2299 int nr = sattr->nr;
2300 int index = sattr->index;
2301
2302 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2303}
2304
2305static ssize_t
2306store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2307 const char *buf, size_t count)
2308{
2309 struct nct6775_data *data = dev_get_drvdata(dev);
2310 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2311 int nr = sattr->nr;
2312 int index = sattr->index;
2313 unsigned long val;
2314 int err;
2315
2316 err = kstrtoul(buf, 10, &val);
2317 if (err < 0)
2318 return err;
2319
2320 /* Limit tolerance as needed */
2321 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2322
2323 mutex_lock(&data->update_lock);
2324 data->temp_tolerance[index][nr] = val;
2325 if (index)
2326 pwm_update_registers(data, nr);
2327 else
2328 nct6775_write_value(data,
2329 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2330 val);
2331 mutex_unlock(&data->update_lock);
2332 return count;
2333}
2334
2335/*
2336 * Fan speed tolerance is a tricky beast, since the associated register is
2337 * a tick counter, but the value is reported and configured as rpm.
2338 * Compute resulting low and high rpm values and report the difference.
2339 */
2340static ssize_t
2341show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2342 char *buf)
2343{
2344 struct nct6775_data *data = nct6775_update_device(dev);
2345 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2346 int nr = sattr->index;
2347 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2348 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2349 int tolerance;
2350
2351 if (low <= 0)
2352 low = 1;
2353 if (high > 0xffff)
2354 high = 0xffff;
2355 if (high < low)
2356 high = low;
2357
2358 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2359 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2360
2361 return sprintf(buf, "%d\n", tolerance);
2362}
2363
2364static ssize_t
2365store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2366 const char *buf, size_t count)
2367{
2368 struct nct6775_data *data = dev_get_drvdata(dev);
2369 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2370 int nr = sattr->index;
2371 unsigned long val;
2372 int err;
2373 int low, high;
2374
2375 err = kstrtoul(buf, 10, &val);
2376 if (err < 0)
2377 return err;
2378
2379 high = fan_from_reg16(data->target_speed[nr],
2380 data->fan_div[nr]) + val;
2381 low = fan_from_reg16(data->target_speed[nr],
2382 data->fan_div[nr]) - val;
2383 if (low <= 0)
2384 low = 1;
2385 if (high < low)
2386 high = low;
2387
2388 val = (fan_to_reg(low, data->fan_div[nr]) -
2389 fan_to_reg(high, data->fan_div[nr])) / 2;
2390
2391 /* Limit tolerance as needed */
2392 val = clamp_val(val, 0, data->speed_tolerance_limit);
2393
2394 mutex_lock(&data->update_lock);
2395 data->target_speed_tolerance[nr] = val;
2396 pwm_update_registers(data, nr);
2397 mutex_unlock(&data->update_lock);
2398 return count;
2399}
2400
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002401static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2402static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0);
2403static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0);
2404static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0);
2405static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0);
2406
2407static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2408 store_pwm_mode, 0);
2409static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2410 store_pwm_mode, 1);
2411static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2412 store_pwm_mode, 2);
2413static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2414 store_pwm_mode, 3);
2415static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
2416 store_pwm_mode, 4);
2417
2418static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2419 store_pwm_enable, 0);
2420static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2421 store_pwm_enable, 1);
2422static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2423 store_pwm_enable, 2);
2424static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2425 store_pwm_enable, 3);
2426static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
2427 store_pwm_enable, 4);
2428
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002429static SENSOR_DEVICE_ATTR(pwm1_temp_sel, S_IWUSR | S_IRUGO,
2430 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2431static SENSOR_DEVICE_ATTR(pwm2_temp_sel, S_IWUSR | S_IRUGO,
2432 show_pwm_temp_sel, store_pwm_temp_sel, 1);
2433static SENSOR_DEVICE_ATTR(pwm3_temp_sel, S_IWUSR | S_IRUGO,
2434 show_pwm_temp_sel, store_pwm_temp_sel, 2);
2435static SENSOR_DEVICE_ATTR(pwm4_temp_sel, S_IWUSR | S_IRUGO,
2436 show_pwm_temp_sel, store_pwm_temp_sel, 3);
2437static SENSOR_DEVICE_ATTR(pwm5_temp_sel, S_IWUSR | S_IRUGO,
2438 show_pwm_temp_sel, store_pwm_temp_sel, 4);
2439
2440static SENSOR_DEVICE_ATTR(pwm1_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2441 store_target_temp, 0);
2442static SENSOR_DEVICE_ATTR(pwm2_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2443 store_target_temp, 1);
2444static SENSOR_DEVICE_ATTR(pwm3_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2445 store_target_temp, 2);
2446static SENSOR_DEVICE_ATTR(pwm4_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2447 store_target_temp, 3);
2448static SENSOR_DEVICE_ATTR(pwm5_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
2449 store_target_temp, 4);
2450
2451static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_target_speed,
2452 store_target_speed, 0);
2453static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_target_speed,
2454 store_target_speed, 1);
2455static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_target_speed,
2456 store_target_speed, 2);
2457static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_target_speed,
2458 store_target_speed, 3);
2459static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_target_speed,
2460 store_target_speed, 4);
2461
2462static SENSOR_DEVICE_ATTR(fan1_tolerance, S_IWUSR | S_IRUGO,
2463 show_speed_tolerance, store_speed_tolerance, 0);
2464static SENSOR_DEVICE_ATTR(fan2_tolerance, S_IWUSR | S_IRUGO,
2465 show_speed_tolerance, store_speed_tolerance, 1);
2466static SENSOR_DEVICE_ATTR(fan3_tolerance, S_IWUSR | S_IRUGO,
2467 show_speed_tolerance, store_speed_tolerance, 2);
2468static SENSOR_DEVICE_ATTR(fan4_tolerance, S_IWUSR | S_IRUGO,
2469 show_speed_tolerance, store_speed_tolerance, 3);
2470static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO,
2471 show_speed_tolerance, store_speed_tolerance, 4);
2472
2473/* Smart Fan registers */
2474
2475static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002476show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2477{
2478 struct nct6775_data *data = nct6775_update_device(dev);
2479 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2480 int nr = sattr->nr;
2481 int index = sattr->index;
2482
2483 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2484}
2485
2486static ssize_t
2487store_weight_temp(struct device *dev, struct device_attribute *attr,
2488 const char *buf, size_t count)
2489{
2490 struct nct6775_data *data = dev_get_drvdata(dev);
2491 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2492 int nr = sattr->nr;
2493 int index = sattr->index;
2494 unsigned long val;
2495 int err;
2496
2497 err = kstrtoul(buf, 10, &val);
2498 if (err < 0)
2499 return err;
2500
2501 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2502
2503 mutex_lock(&data->update_lock);
2504 data->weight_temp[index][nr] = val;
2505 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2506 mutex_unlock(&data->update_lock);
2507 return count;
2508}
2509
2510static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO,
2511 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2512 0);
2513static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO,
2514 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2515 1);
2516static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO,
2517 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2518 2);
2519static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO,
2520 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2521 3);
2522static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO,
2523 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
2524 4);
2525
2526static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO,
2527 show_weight_temp, store_weight_temp, 0, 0);
2528static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO,
2529 show_weight_temp, store_weight_temp, 1, 0);
2530static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO,
2531 show_weight_temp, store_weight_temp, 2, 0);
2532static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO,
2533 show_weight_temp, store_weight_temp, 3, 0);
2534static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO,
2535 show_weight_temp, store_weight_temp, 4, 0);
2536
2537static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2538 show_weight_temp, store_weight_temp, 0, 1);
2539static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2540 show_weight_temp, store_weight_temp, 1, 1);
2541static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2542 show_weight_temp, store_weight_temp, 2, 1);
2543static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2544 show_weight_temp, store_weight_temp, 3, 1);
2545static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO,
2546 show_weight_temp, store_weight_temp, 4, 1);
2547
2548static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO,
2549 show_weight_temp, store_weight_temp, 0, 2);
2550static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO,
2551 show_weight_temp, store_weight_temp, 1, 2);
2552static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO,
2553 show_weight_temp, store_weight_temp, 2, 2);
2554static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO,
2555 show_weight_temp, store_weight_temp, 3, 2);
2556static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO,
2557 show_weight_temp, store_weight_temp, 4, 2);
2558
2559static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO,
2560 show_pwm, store_pwm, 0, 5);
2561static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO,
2562 show_pwm, store_pwm, 1, 5);
2563static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO,
2564 show_pwm, store_pwm, 2, 5);
2565static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO,
2566 show_pwm, store_pwm, 3, 5);
2567static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO,
2568 show_pwm, store_pwm, 4, 5);
2569
2570/* duty_base is not supported on all chips */
2571static struct sensor_device_attribute_2 sda_weight_duty_base[] = {
2572 SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO,
2573 show_pwm, store_pwm, 0, 6),
2574 SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO,
2575 show_pwm, store_pwm, 1, 6),
2576 SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO,
2577 show_pwm, store_pwm, 2, 6),
2578 SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO,
2579 show_pwm, store_pwm, 3, 6),
2580 SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO,
2581 show_pwm, store_pwm, 4, 6),
2582};
2583
2584static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002585show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2586{
2587 struct nct6775_data *data = nct6775_update_device(dev);
2588 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2589 int nr = sattr->nr;
2590 int index = sattr->index;
2591
2592 return sprintf(buf, "%d\n",
2593 step_time_from_reg(data->fan_time[index][nr],
2594 data->pwm_mode[nr]));
2595}
2596
2597static ssize_t
2598store_fan_time(struct device *dev, struct device_attribute *attr,
2599 const char *buf, size_t count)
2600{
2601 struct nct6775_data *data = dev_get_drvdata(dev);
2602 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2603 int nr = sattr->nr;
2604 int index = sattr->index;
2605 unsigned long val;
2606 int err;
2607
2608 err = kstrtoul(buf, 10, &val);
2609 if (err < 0)
2610 return err;
2611
2612 val = step_time_to_reg(val, data->pwm_mode[nr]);
2613 mutex_lock(&data->update_lock);
2614 data->fan_time[index][nr] = val;
2615 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2616 mutex_unlock(&data->update_lock);
2617 return count;
2618}
2619
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002620static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002621show_name(struct device *dev, struct device_attribute *attr, char *buf)
2622{
2623 struct nct6775_data *data = dev_get_drvdata(dev);
2624
2625 return sprintf(buf, "%s\n", data->name);
2626}
2627
2628static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2629
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002630static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2631 store_fan_time, 0, 0);
2632static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2633 store_fan_time, 1, 0);
2634static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2635 store_fan_time, 2, 0);
2636static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2637 store_fan_time, 3, 0);
2638static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
2639 store_fan_time, 4, 0);
2640
2641static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2642 store_fan_time, 0, 1);
2643static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2644 store_fan_time, 1, 1);
2645static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2646 store_fan_time, 2, 1);
2647static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2648 store_fan_time, 3, 1);
2649static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
2650 store_fan_time, 4, 1);
2651
2652static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO,
2653 show_fan_time, store_fan_time, 0, 2);
2654static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO,
2655 show_fan_time, store_fan_time, 1, 2);
2656static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO,
2657 show_fan_time, store_fan_time, 2, 2);
2658static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO,
2659 show_fan_time, store_fan_time, 3, 2);
2660static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO,
2661 show_fan_time, store_fan_time, 4, 2);
2662
2663static SENSOR_DEVICE_ATTR_2(pwm1_start, S_IWUSR | S_IRUGO, show_pwm,
2664 store_pwm, 0, 1);
2665static SENSOR_DEVICE_ATTR_2(pwm2_start, S_IWUSR | S_IRUGO, show_pwm,
2666 store_pwm, 1, 1);
2667static SENSOR_DEVICE_ATTR_2(pwm3_start, S_IWUSR | S_IRUGO, show_pwm,
2668 store_pwm, 2, 1);
2669static SENSOR_DEVICE_ATTR_2(pwm4_start, S_IWUSR | S_IRUGO, show_pwm,
2670 store_pwm, 3, 1);
2671static SENSOR_DEVICE_ATTR_2(pwm5_start, S_IWUSR | S_IRUGO, show_pwm,
2672 store_pwm, 4, 1);
2673
2674static SENSOR_DEVICE_ATTR_2(pwm1_floor, S_IWUSR | S_IRUGO, show_pwm,
2675 store_pwm, 0, 2);
2676static SENSOR_DEVICE_ATTR_2(pwm2_floor, S_IWUSR | S_IRUGO, show_pwm,
2677 store_pwm, 1, 2);
2678static SENSOR_DEVICE_ATTR_2(pwm3_floor, S_IWUSR | S_IRUGO, show_pwm,
2679 store_pwm, 2, 2);
2680static SENSOR_DEVICE_ATTR_2(pwm4_floor, S_IWUSR | S_IRUGO, show_pwm,
2681 store_pwm, 3, 2);
2682static SENSOR_DEVICE_ATTR_2(pwm5_floor, S_IWUSR | S_IRUGO, show_pwm,
2683 store_pwm, 4, 2);
2684
2685static SENSOR_DEVICE_ATTR_2(pwm1_temp_tolerance, S_IWUSR | S_IRUGO,
2686 show_temp_tolerance, store_temp_tolerance, 0, 0);
2687static SENSOR_DEVICE_ATTR_2(pwm2_temp_tolerance, S_IWUSR | S_IRUGO,
2688 show_temp_tolerance, store_temp_tolerance, 1, 0);
2689static SENSOR_DEVICE_ATTR_2(pwm3_temp_tolerance, S_IWUSR | S_IRUGO,
2690 show_temp_tolerance, store_temp_tolerance, 2, 0);
2691static SENSOR_DEVICE_ATTR_2(pwm4_temp_tolerance, S_IWUSR | S_IRUGO,
2692 show_temp_tolerance, store_temp_tolerance, 3, 0);
2693static SENSOR_DEVICE_ATTR_2(pwm5_temp_tolerance, S_IWUSR | S_IRUGO,
2694 show_temp_tolerance, store_temp_tolerance, 4, 0);
2695
2696static SENSOR_DEVICE_ATTR_2(pwm1_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2697 show_temp_tolerance, store_temp_tolerance, 0, 1);
2698static SENSOR_DEVICE_ATTR_2(pwm2_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2699 show_temp_tolerance, store_temp_tolerance, 1, 1);
2700static SENSOR_DEVICE_ATTR_2(pwm3_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2701 show_temp_tolerance, store_temp_tolerance, 2, 1);
2702static SENSOR_DEVICE_ATTR_2(pwm4_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2703 show_temp_tolerance, store_temp_tolerance, 3, 1);
2704static SENSOR_DEVICE_ATTR_2(pwm5_crit_temp_tolerance, S_IWUSR | S_IRUGO,
2705 show_temp_tolerance, store_temp_tolerance, 4, 1);
2706
2707/* pwm_max is not supported on all chips */
2708static struct sensor_device_attribute_2 sda_pwm_max[] = {
2709 SENSOR_ATTR_2(pwm1_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2710 0, 3),
2711 SENSOR_ATTR_2(pwm2_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2712 1, 3),
2713 SENSOR_ATTR_2(pwm3_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2714 2, 3),
2715 SENSOR_ATTR_2(pwm4_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2716 3, 3),
2717 SENSOR_ATTR_2(pwm5_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2718 4, 3),
2719};
2720
2721/* pwm_step is not supported on all chips */
2722static struct sensor_device_attribute_2 sda_pwm_step[] = {
2723 SENSOR_ATTR_2(pwm1_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 4),
2724 SENSOR_ATTR_2(pwm2_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 4),
2725 SENSOR_ATTR_2(pwm3_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 4),
2726 SENSOR_ATTR_2(pwm4_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 4),
2727 SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4),
2728};
2729
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002730static struct attribute *nct6775_attributes_pwm[5][20] = {
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002731 {
2732 &sensor_dev_attr_pwm1.dev_attr.attr,
2733 &sensor_dev_attr_pwm1_mode.dev_attr.attr,
2734 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002735 &sensor_dev_attr_pwm1_temp_sel.dev_attr.attr,
2736 &sensor_dev_attr_pwm1_temp_tolerance.dev_attr.attr,
2737 &sensor_dev_attr_pwm1_crit_temp_tolerance.dev_attr.attr,
2738 &sensor_dev_attr_pwm1_target_temp.dev_attr.attr,
2739 &sensor_dev_attr_fan1_target.dev_attr.attr,
2740 &sensor_dev_attr_fan1_tolerance.dev_attr.attr,
2741 &sensor_dev_attr_pwm1_stop_time.dev_attr.attr,
2742 &sensor_dev_attr_pwm1_step_up_time.dev_attr.attr,
2743 &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr,
2744 &sensor_dev_attr_pwm1_start.dev_attr.attr,
2745 &sensor_dev_attr_pwm1_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002746 &sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr,
2747 &sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr,
2748 &sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr,
2749 &sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr,
2750 &sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002751 NULL
2752 },
2753 {
2754 &sensor_dev_attr_pwm2.dev_attr.attr,
2755 &sensor_dev_attr_pwm2_mode.dev_attr.attr,
2756 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002757 &sensor_dev_attr_pwm2_temp_sel.dev_attr.attr,
2758 &sensor_dev_attr_pwm2_temp_tolerance.dev_attr.attr,
2759 &sensor_dev_attr_pwm2_crit_temp_tolerance.dev_attr.attr,
2760 &sensor_dev_attr_pwm2_target_temp.dev_attr.attr,
2761 &sensor_dev_attr_fan2_target.dev_attr.attr,
2762 &sensor_dev_attr_fan2_tolerance.dev_attr.attr,
2763 &sensor_dev_attr_pwm2_stop_time.dev_attr.attr,
2764 &sensor_dev_attr_pwm2_step_up_time.dev_attr.attr,
2765 &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr,
2766 &sensor_dev_attr_pwm2_start.dev_attr.attr,
2767 &sensor_dev_attr_pwm2_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002768 &sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr,
2769 &sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr,
2770 &sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr,
2771 &sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr,
2772 &sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002773 NULL
2774 },
2775 {
2776 &sensor_dev_attr_pwm3.dev_attr.attr,
2777 &sensor_dev_attr_pwm3_mode.dev_attr.attr,
2778 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002779 &sensor_dev_attr_pwm3_temp_sel.dev_attr.attr,
2780 &sensor_dev_attr_pwm3_temp_tolerance.dev_attr.attr,
2781 &sensor_dev_attr_pwm3_crit_temp_tolerance.dev_attr.attr,
2782 &sensor_dev_attr_pwm3_target_temp.dev_attr.attr,
2783 &sensor_dev_attr_fan3_target.dev_attr.attr,
2784 &sensor_dev_attr_fan3_tolerance.dev_attr.attr,
2785 &sensor_dev_attr_pwm3_stop_time.dev_attr.attr,
2786 &sensor_dev_attr_pwm3_step_up_time.dev_attr.attr,
2787 &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr,
2788 &sensor_dev_attr_pwm3_start.dev_attr.attr,
2789 &sensor_dev_attr_pwm3_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002790 &sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr,
2791 &sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr,
2792 &sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr,
2793 &sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr,
2794 &sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002795 NULL
2796 },
2797 {
2798 &sensor_dev_attr_pwm4.dev_attr.attr,
2799 &sensor_dev_attr_pwm4_mode.dev_attr.attr,
2800 &sensor_dev_attr_pwm4_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002801 &sensor_dev_attr_pwm4_temp_sel.dev_attr.attr,
2802 &sensor_dev_attr_pwm4_temp_tolerance.dev_attr.attr,
2803 &sensor_dev_attr_pwm4_crit_temp_tolerance.dev_attr.attr,
2804 &sensor_dev_attr_pwm4_target_temp.dev_attr.attr,
2805 &sensor_dev_attr_fan4_target.dev_attr.attr,
2806 &sensor_dev_attr_fan4_tolerance.dev_attr.attr,
2807 &sensor_dev_attr_pwm4_stop_time.dev_attr.attr,
2808 &sensor_dev_attr_pwm4_step_up_time.dev_attr.attr,
2809 &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr,
2810 &sensor_dev_attr_pwm4_start.dev_attr.attr,
2811 &sensor_dev_attr_pwm4_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002812 &sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr,
2813 &sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr,
2814 &sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr,
2815 &sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr,
2816 &sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002817 NULL
2818 },
2819 {
2820 &sensor_dev_attr_pwm5.dev_attr.attr,
2821 &sensor_dev_attr_pwm5_mode.dev_attr.attr,
2822 &sensor_dev_attr_pwm5_enable.dev_attr.attr,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002823 &sensor_dev_attr_pwm5_temp_sel.dev_attr.attr,
2824 &sensor_dev_attr_pwm5_temp_tolerance.dev_attr.attr,
2825 &sensor_dev_attr_pwm5_crit_temp_tolerance.dev_attr.attr,
2826 &sensor_dev_attr_pwm5_target_temp.dev_attr.attr,
2827 &sensor_dev_attr_fan5_target.dev_attr.attr,
2828 &sensor_dev_attr_fan5_tolerance.dev_attr.attr,
2829 &sensor_dev_attr_pwm5_stop_time.dev_attr.attr,
2830 &sensor_dev_attr_pwm5_step_up_time.dev_attr.attr,
2831 &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr,
2832 &sensor_dev_attr_pwm5_start.dev_attr.attr,
2833 &sensor_dev_attr_pwm5_floor.dev_attr.attr,
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002834 &sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr,
2835 &sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr,
2836 &sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr,
2837 &sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr,
2838 &sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr,
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002839 NULL
2840 },
2841};
2842
2843static const struct attribute_group nct6775_group_pwm[5] = {
2844 { .attrs = nct6775_attributes_pwm[0] },
2845 { .attrs = nct6775_attributes_pwm[1] },
2846 { .attrs = nct6775_attributes_pwm[2] },
2847 { .attrs = nct6775_attributes_pwm[3] },
2848 { .attrs = nct6775_attributes_pwm[4] },
2849};
2850
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002851static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002852show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2853{
2854 struct nct6775_data *data = nct6775_update_device(dev);
2855 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2856
2857 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2858}
2859
2860static ssize_t
2861store_auto_pwm(struct device *dev, struct device_attribute *attr,
2862 const char *buf, size_t count)
2863{
2864 struct nct6775_data *data = dev_get_drvdata(dev);
2865 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2866 int nr = sattr->nr;
2867 int point = sattr->index;
2868 unsigned long val;
2869 int err;
2870 u8 reg;
2871
2872 err = kstrtoul(buf, 10, &val);
2873 if (err < 0)
2874 return err;
2875 if (val > 255)
2876 return -EINVAL;
2877
2878 if (point == data->auto_pwm_num) {
2879 if (data->kind != nct6775 && !val)
2880 return -EINVAL;
2881 if (data->kind != nct6779 && val)
2882 val = 0xff;
2883 }
2884
2885 mutex_lock(&data->update_lock);
2886 data->auto_pwm[nr][point] = val;
2887 if (point < data->auto_pwm_num) {
2888 nct6775_write_value(data,
2889 NCT6775_AUTO_PWM(data, nr, point),
2890 data->auto_pwm[nr][point]);
2891 } else {
2892 switch (data->kind) {
2893 case nct6775:
2894 /* disable if needed (pwm == 0) */
2895 reg = nct6775_read_value(data,
2896 NCT6775_REG_CRITICAL_ENAB[nr]);
2897 if (val)
2898 reg |= 0x02;
2899 else
2900 reg &= ~0x02;
2901 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2902 reg);
2903 break;
2904 case nct6776:
2905 break; /* always enabled, nothing to do */
2906 case nct6779:
2907 nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr],
2908 val);
2909 reg = nct6775_read_value(data,
2910 NCT6779_REG_CRITICAL_PWM_ENABLE[nr]);
2911 if (val == 255)
2912 reg &= ~0x01;
2913 else
2914 reg |= 0x01;
2915 nct6775_write_value(data,
2916 NCT6779_REG_CRITICAL_PWM_ENABLE[nr],
2917 reg);
2918 break;
2919 }
2920 }
2921 mutex_unlock(&data->update_lock);
2922 return count;
2923}
2924
2925static ssize_t
2926show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2927{
2928 struct nct6775_data *data = nct6775_update_device(dev);
2929 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2930 int nr = sattr->nr;
2931 int point = sattr->index;
2932
2933 /*
2934 * We don't know for sure if the temperature is signed or unsigned.
2935 * Assume it is unsigned.
2936 */
2937 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2938}
2939
2940static ssize_t
2941store_auto_temp(struct device *dev, struct device_attribute *attr,
2942 const char *buf, size_t count)
2943{
2944 struct nct6775_data *data = dev_get_drvdata(dev);
2945 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2946 int nr = sattr->nr;
2947 int point = sattr->index;
2948 unsigned long val;
2949 int err;
2950
2951 err = kstrtoul(buf, 10, &val);
2952 if (err)
2953 return err;
2954 if (val > 255000)
2955 return -EINVAL;
2956
2957 mutex_lock(&data->update_lock);
2958 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2959 if (point < data->auto_pwm_num) {
2960 nct6775_write_value(data,
2961 NCT6775_AUTO_TEMP(data, nr, point),
2962 data->auto_temp[nr][point]);
2963 } else {
2964 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2965 data->auto_temp[nr][point]);
2966 }
2967 mutex_unlock(&data->update_lock);
2968 return count;
2969}
2970
2971/*
2972 * The number of auto-point trip points is chip dependent.
2973 * Need to check support while generating/removing attribute files.
2974 */
2975static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = {
2976 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
2977 show_auto_pwm, store_auto_pwm, 0, 0),
2978 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
2979 show_auto_temp, store_auto_temp, 0, 0),
2980 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
2981 show_auto_pwm, store_auto_pwm, 0, 1),
2982 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
2983 show_auto_temp, store_auto_temp, 0, 1),
2984 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
2985 show_auto_pwm, store_auto_pwm, 0, 2),
2986 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
2987 show_auto_temp, store_auto_temp, 0, 2),
2988 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
2989 show_auto_pwm, store_auto_pwm, 0, 3),
2990 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
2991 show_auto_temp, store_auto_temp, 0, 3),
2992 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
2993 show_auto_pwm, store_auto_pwm, 0, 4),
2994 SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
2995 show_auto_temp, store_auto_temp, 0, 4),
2996 SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
2997 show_auto_pwm, store_auto_pwm, 0, 5),
2998 SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
2999 show_auto_temp, store_auto_temp, 0, 5),
3000 SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
3001 show_auto_pwm, store_auto_pwm, 0, 6),
3002 SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
3003 show_auto_temp, store_auto_temp, 0, 6),
3004
3005 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
3006 show_auto_pwm, store_auto_pwm, 1, 0),
3007 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO,
3008 show_auto_temp, store_auto_temp, 1, 0),
3009 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
3010 show_auto_pwm, store_auto_pwm, 1, 1),
3011 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO,
3012 show_auto_temp, store_auto_temp, 1, 1),
3013 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO,
3014 show_auto_pwm, store_auto_pwm, 1, 2),
3015 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO,
3016 show_auto_temp, store_auto_temp, 1, 2),
3017 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO,
3018 show_auto_pwm, store_auto_pwm, 1, 3),
3019 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO,
3020 show_auto_temp, store_auto_temp, 1, 3),
3021 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO,
3022 show_auto_pwm, store_auto_pwm, 1, 4),
3023 SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO,
3024 show_auto_temp, store_auto_temp, 1, 4),
3025 SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO,
3026 show_auto_pwm, store_auto_pwm, 1, 5),
3027 SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO,
3028 show_auto_temp, store_auto_temp, 1, 5),
3029 SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO,
3030 show_auto_pwm, store_auto_pwm, 1, 6),
3031 SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO,
3032 show_auto_temp, store_auto_temp, 1, 6),
3033
3034 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
3035 show_auto_pwm, store_auto_pwm, 2, 0),
3036 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO,
3037 show_auto_temp, store_auto_temp, 2, 0),
3038 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
3039 show_auto_pwm, store_auto_pwm, 2, 1),
3040 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO,
3041 show_auto_temp, store_auto_temp, 2, 1),
3042 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO,
3043 show_auto_pwm, store_auto_pwm, 2, 2),
3044 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO,
3045 show_auto_temp, store_auto_temp, 2, 2),
3046 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO,
3047 show_auto_pwm, store_auto_pwm, 2, 3),
3048 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO,
3049 show_auto_temp, store_auto_temp, 2, 3),
3050 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO,
3051 show_auto_pwm, store_auto_pwm, 2, 4),
3052 SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO,
3053 show_auto_temp, store_auto_temp, 2, 4),
3054 SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO,
3055 show_auto_pwm, store_auto_pwm, 2, 5),
3056 SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO,
3057 show_auto_temp, store_auto_temp, 2, 5),
3058 SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO,
3059 show_auto_pwm, store_auto_pwm, 2, 6),
3060 SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO,
3061 show_auto_temp, store_auto_temp, 2, 6),
3062
3063 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
3064 show_auto_pwm, store_auto_pwm, 3, 0),
3065 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO,
3066 show_auto_temp, store_auto_temp, 3, 0),
3067 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
3068 show_auto_pwm, store_auto_pwm, 3, 1),
3069 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO,
3070 show_auto_temp, store_auto_temp, 3, 1),
3071 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO,
3072 show_auto_pwm, store_auto_pwm, 3, 2),
3073 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO,
3074 show_auto_temp, store_auto_temp, 3, 2),
3075 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO,
3076 show_auto_pwm, store_auto_pwm, 3, 3),
3077 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO,
3078 show_auto_temp, store_auto_temp, 3, 3),
3079 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO,
3080 show_auto_pwm, store_auto_pwm, 3, 4),
3081 SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO,
3082 show_auto_temp, store_auto_temp, 3, 4),
3083 SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO,
3084 show_auto_pwm, store_auto_pwm, 3, 5),
3085 SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO,
3086 show_auto_temp, store_auto_temp, 3, 5),
3087 SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO,
3088 show_auto_pwm, store_auto_pwm, 3, 6),
3089 SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO,
3090 show_auto_temp, store_auto_temp, 3, 6),
3091
3092 SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO,
3093 show_auto_pwm, store_auto_pwm, 4, 0),
3094 SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO,
3095 show_auto_temp, store_auto_temp, 4, 0),
3096 SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO,
3097 show_auto_pwm, store_auto_pwm, 4, 1),
3098 SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO,
3099 show_auto_temp, store_auto_temp, 4, 1),
3100 SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO,
3101 show_auto_pwm, store_auto_pwm, 4, 2),
3102 SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO,
3103 show_auto_temp, store_auto_temp, 4, 2),
3104 SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO,
3105 show_auto_pwm, store_auto_pwm, 4, 3),
3106 SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO,
3107 show_auto_temp, store_auto_temp, 4, 3),
3108 SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO,
3109 show_auto_pwm, store_auto_pwm, 4, 4),
3110 SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO,
3111 show_auto_temp, store_auto_temp, 4, 4),
3112 SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO,
3113 show_auto_pwm, store_auto_pwm, 4, 5),
3114 SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO,
3115 show_auto_temp, store_auto_temp, 4, 5),
3116 SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO,
3117 show_auto_pwm, store_auto_pwm, 4, 6),
3118 SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO,
3119 show_auto_temp, store_auto_temp, 4, 6),
3120};
3121
3122static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003123show_vid(struct device *dev, struct device_attribute *attr, char *buf)
3124{
3125 struct nct6775_data *data = dev_get_drvdata(dev);
3126 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3127}
3128
3129static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3130
Guenter Roecka6bd5872012-12-04 03:13:34 -08003131/* Case open detection */
3132
3133static ssize_t
3134clear_caseopen(struct device *dev, struct device_attribute *attr,
3135 const char *buf, size_t count)
3136{
3137 struct nct6775_data *data = dev_get_drvdata(dev);
3138 struct nct6775_sio_data *sio_data = dev->platform_data;
3139 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3140 unsigned long val;
3141 u8 reg;
3142 int ret;
3143
3144 if (kstrtoul(buf, 10, &val) || val != 0)
3145 return -EINVAL;
3146
3147 mutex_lock(&data->update_lock);
3148
3149 /*
3150 * Use CR registers to clear caseopen status.
3151 * The CR registers are the same for all chips, and not all chips
3152 * support clearing the caseopen status through "regular" registers.
3153 */
3154 ret = superio_enter(sio_data->sioreg);
3155 if (ret) {
3156 count = ret;
3157 goto error;
3158 }
3159
3160 superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
3161 reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
3162 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
3163 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3164 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
3165 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3166 superio_exit(sio_data->sioreg);
3167
3168 data->valid = false; /* Force cache refresh */
3169error:
3170 mutex_unlock(&data->update_lock);
3171 return count;
3172}
3173
3174static struct sensor_device_attribute sda_caseopen[] = {
3175 SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3176 clear_caseopen, INTRUSION_ALARM_BASE),
3177 SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3178 clear_caseopen, INTRUSION_ALARM_BASE + 1),
3179};
3180
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003181/*
3182 * Driver and device management
3183 */
3184
3185static void nct6775_device_remove_files(struct device *dev)
3186{
3187 /*
3188 * some entries in the following arrays may not have been used in
3189 * device_create_file(), but device_remove_file() will ignore them
3190 */
3191 int i;
3192 struct nct6775_data *data = dev_get_drvdata(dev);
3193
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003194 for (i = 0; i < data->pwm_num; i++)
3195 sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]);
3196
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003197 for (i = 0; i < ARRAY_SIZE(sda_pwm_max); i++)
3198 device_remove_file(dev, &sda_pwm_max[i].dev_attr);
3199
3200 for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++)
3201 device_remove_file(dev, &sda_pwm_step[i].dev_attr);
3202
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003203 for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++)
3204 device_remove_file(dev, &sda_weight_duty_base[i].dev_attr);
3205
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003206 for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++)
3207 device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr);
3208
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003209 for (i = 0; i < data->in_num; i++)
3210 sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]);
3211
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003212 for (i = 0; i < 5; i++) {
3213 device_remove_file(dev, &sda_fan_input[i].dev_attr);
3214 device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
3215 device_remove_file(dev, &sda_fan_div[i].dev_attr);
3216 device_remove_file(dev, &sda_fan_min[i].dev_attr);
Guenter Roeck5c25d952012-12-11 07:29:06 -08003217 device_remove_file(dev, &sda_fan_pulses[i].dev_attr);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003218 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003219 for (i = 0; i < NUM_TEMP; i++) {
3220 if (!(data->have_temp & (1 << i)))
3221 continue;
3222 device_remove_file(dev, &sda_temp_input[i].dev_attr);
3223 device_remove_file(dev, &sda_temp_label[i].dev_attr);
3224 device_remove_file(dev, &sda_temp_max[i].dev_attr);
3225 device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
3226 device_remove_file(dev, &sda_temp_crit[i].dev_attr);
3227 if (!(data->have_temp_fixed & (1 << i)))
3228 continue;
3229 device_remove_file(dev, &sda_temp_type[i].dev_attr);
3230 device_remove_file(dev, &sda_temp_offset[i].dev_attr);
3231 if (i >= NUM_TEMP_ALARM)
3232 continue;
3233 device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
3234 }
3235
Guenter Roecka6bd5872012-12-04 03:13:34 -08003236 device_remove_file(dev, &sda_caseopen[0].dev_attr);
3237 device_remove_file(dev, &sda_caseopen[1].dev_attr);
3238
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003239 device_remove_file(dev, &dev_attr_name);
3240 device_remove_file(dev, &dev_attr_cpu0_vid);
3241}
3242
3243/* Get the monitoring functions started */
3244static inline void nct6775_init_device(struct nct6775_data *data)
3245{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003246 int i;
3247 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003248
3249 /* Start monitoring if needed */
3250 if (data->REG_CONFIG) {
3251 tmp = nct6775_read_value(data, data->REG_CONFIG);
3252 if (!(tmp & 0x01))
3253 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3254 }
3255
Guenter Roeckaa136e52012-12-04 03:26:05 -08003256 /* Enable temperature sensors if needed */
3257 for (i = 0; i < NUM_TEMP; i++) {
3258 if (!(data->have_temp & (1 << i)))
3259 continue;
3260 if (!data->reg_temp_config[i])
3261 continue;
3262 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3263 if (tmp & 0x01)
3264 nct6775_write_value(data, data->reg_temp_config[i],
3265 tmp & 0xfe);
3266 }
3267
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003268 /* Enable VBAT monitoring if needed */
3269 tmp = nct6775_read_value(data, data->REG_VBAT);
3270 if (!(tmp & 0x01))
3271 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003272
3273 diode = nct6775_read_value(data, data->REG_DIODE);
3274
3275 for (i = 0; i < data->temp_fixed_num; i++) {
3276 if (!(data->have_temp_fixed & (1 << i)))
3277 continue;
3278 if ((tmp & (0x02 << i))) /* diode */
3279 data->temp_type[i] = 3 - ((diode >> i) & 0x02);
3280 else /* thermistor */
3281 data->temp_type[i] = 4;
3282 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003283}
3284
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003285static int
3286nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
3287 struct nct6775_data *data)
3288{
3289 int regval;
3290 bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003291 bool pwm3pin, pwm4pin, pwm5pin;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003292 int ret;
3293
3294 ret = superio_enter(sio_data->sioreg);
3295 if (ret)
3296 return ret;
3297
3298 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3299 if (data->kind == nct6775) {
3300 regval = superio_inb(sio_data->sioreg, 0x2c);
3301
3302 fan3pin = regval & (1 << 6);
3303 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003304 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003305
3306 /* On NCT6775, fan4 shares pins with the fdc interface */
3307 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
3308 fan4min = 0;
3309 fan5pin = 0;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003310 pwm4pin = 0;
3311 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003312 } else if (data->kind == nct6776) {
3313 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
3314
3315 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3316 regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
3317
3318 if (regval & 0x80)
3319 fan3pin = gpok;
3320 else
3321 fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
3322
3323 if (regval & 0x40)
3324 fan4pin = gpok;
3325 else
3326 fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
3327
3328 if (regval & 0x20)
3329 fan5pin = gpok;
3330 else
3331 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
3332
3333 fan4min = fan4pin;
3334 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003335 pwm3pin = fan3pin;
3336 pwm4pin = 0;
3337 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003338 } else { /* NCT6779D */
3339 regval = superio_inb(sio_data->sioreg, 0x1c);
3340
3341 fan3pin = !(regval & (1 << 5));
3342 fan4pin = !(regval & (1 << 6));
3343 fan5pin = !(regval & (1 << 7));
3344
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003345 pwm3pin = !(regval & (1 << 0));
3346 pwm4pin = !(regval & (1 << 1));
3347 pwm5pin = !(regval & (1 << 2));
3348
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003349 fan3min = fan3pin;
3350 fan4min = fan4pin;
3351 }
3352
3353 superio_exit(sio_data->sioreg);
3354
3355 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
3356 data->has_fan |= fan3pin << 2;
3357 data->has_fan_min |= fan3min << 2;
3358
3359 data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
3360 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
3361
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003362 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
3363
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003364 return 0;
3365}
3366
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003367static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3368 int *available, int *mask)
3369{
3370 int i;
3371 u8 src;
3372
3373 for (i = 0; i < data->pwm_num && *available; i++) {
3374 int index;
3375
3376 if (!regp[i])
3377 continue;
3378 src = nct6775_read_value(data, regp[i]);
3379 src &= 0x1f;
3380 if (!src || (*mask & (1 << src)))
3381 continue;
3382 if (src >= data->temp_label_num ||
3383 !strlen(data->temp_label[src]))
3384 continue;
3385
3386 index = __ffs(*available);
3387 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3388 *available &= ~(1 << index);
3389 *mask |= 1 << src;
3390 }
3391}
3392
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003393static int nct6775_probe(struct platform_device *pdev)
3394{
3395 struct device *dev = &pdev->dev;
3396 struct nct6775_sio_data *sio_data = dev->platform_data;
3397 struct nct6775_data *data;
3398 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003399 int i, s, err = 0;
3400 int src, mask, available;
3401 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3402 const u16 *reg_temp_alternate, *reg_temp_crit;
3403 int num_reg_temp;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003404
3405 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3406 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3407 DRVNAME))
3408 return -EBUSY;
3409
3410 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3411 GFP_KERNEL);
3412 if (!data)
3413 return -ENOMEM;
3414
3415 data->kind = sio_data->kind;
3416 data->addr = res->start;
3417 mutex_init(&data->lock);
3418 mutex_init(&data->update_lock);
3419 data->name = nct6775_device_names[data->kind];
3420 data->bank = 0xff; /* Force initial bank selection */
3421 platform_set_drvdata(pdev, data);
3422
3423 switch (data->kind) {
3424 case nct6775:
3425 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003426 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003427 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003428 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003429 data->temp_fixed_num = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003430
3431 data->ALARM_BITS = NCT6775_ALARM_BITS;
3432
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003433 data->fan_from_reg = fan_from_reg16;
3434 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003435 data->target_temp_mask = 0x7f;
3436 data->tolerance_mask = 0x0f;
3437 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003438
Guenter Roeckaa136e52012-12-04 03:26:05 -08003439 data->temp_label = nct6775_temp_label;
3440 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3441
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003442 data->REG_CONFIG = NCT6775_REG_CONFIG;
3443 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003444 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003445 data->REG_VIN = NCT6775_REG_IN;
3446 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3447 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003448 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003449 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003450 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003451 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003452 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003453 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3454 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3455 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003456 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003457 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3458 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3459 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3460 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003461 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003462 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3463 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3464 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003465 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3466 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3467 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3468 data->REG_CRITICAL_TEMP_TOLERANCE
3469 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003470 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3471 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003472 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003473 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3474 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3475 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3476 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003477 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003478
3479 reg_temp = NCT6775_REG_TEMP;
3480 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3481 reg_temp_over = NCT6775_REG_TEMP_OVER;
3482 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3483 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3484 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3485 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3486
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003487 break;
3488 case nct6776:
3489 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003490 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003491 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003492 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003493 data->temp_fixed_num = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003494
3495 data->ALARM_BITS = NCT6776_ALARM_BITS;
3496
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003497 data->fan_from_reg = fan_from_reg13;
3498 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003499 data->target_temp_mask = 0xff;
3500 data->tolerance_mask = 0x07;
3501 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003502
Guenter Roeckaa136e52012-12-04 03:26:05 -08003503 data->temp_label = nct6776_temp_label;
3504 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3505
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003506 data->REG_CONFIG = NCT6775_REG_CONFIG;
3507 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003508 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003509 data->REG_VIN = NCT6775_REG_IN;
3510 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3511 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003512 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003513 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003514 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003515 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003516 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003517 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3518 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3519 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3520 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003521 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003522 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3523 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003524 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3525 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003526 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3527 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3528 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003529 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3530 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3531 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3532 data->REG_CRITICAL_TEMP_TOLERANCE
3533 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003534 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3535 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003536 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003537 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3538 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3539 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3540 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003541 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003542
3543 reg_temp = NCT6775_REG_TEMP;
3544 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3545 reg_temp_over = NCT6775_REG_TEMP_OVER;
3546 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3547 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3548 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3549 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3550
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003551 break;
3552 case nct6779:
3553 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003554 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003555 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003556 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003557 data->temp_fixed_num = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003558
3559 data->ALARM_BITS = NCT6779_ALARM_BITS;
3560
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003561 data->fan_from_reg = fan_from_reg13;
3562 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003563 data->target_temp_mask = 0xff;
3564 data->tolerance_mask = 0x07;
3565 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003566
Guenter Roeckaa136e52012-12-04 03:26:05 -08003567 data->temp_label = nct6779_temp_label;
3568 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3569
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003570 data->REG_CONFIG = NCT6775_REG_CONFIG;
3571 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003572 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003573 data->REG_VIN = NCT6779_REG_IN;
3574 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3575 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003576 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003577 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003578 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003579 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003580 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003581 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3582 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3583 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3584 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003585 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003586 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3587 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003588 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3589 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003590 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3591 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3592 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003593 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3594 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3595 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3596 data->REG_CRITICAL_TEMP_TOLERANCE
3597 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003598 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3599 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003600 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003601 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3602 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3603 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3604 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003605 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003606
3607 reg_temp = NCT6779_REG_TEMP;
3608 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3609 reg_temp_over = NCT6779_REG_TEMP_OVER;
3610 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3611 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3612 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3613 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3614
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003615 break;
3616 default:
3617 return -ENODEV;
3618 }
3619 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003620 data->have_temp = 0;
3621
3622 /*
3623 * On some boards, not all available temperature sources are monitored,
3624 * even though some of the monitoring registers are unused.
3625 * Get list of unused monitoring registers, then detect if any fan
3626 * controls are configured to use unmonitored temperature sources.
3627 * If so, assign the unmonitored temperature sources to available
3628 * monitoring registers.
3629 */
3630 mask = 0;
3631 available = 0;
3632 for (i = 0; i < num_reg_temp; i++) {
3633 if (reg_temp[i] == 0)
3634 continue;
3635
3636 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3637 if (!src || (mask & (1 << src)))
3638 available |= 1 << i;
3639
3640 mask |= 1 << src;
3641 }
3642
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003643 /*
3644 * Now find unmonitored temperature registers and enable monitoring
3645 * if additional monitoring registers are available.
3646 */
3647 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3648 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3649
Guenter Roeckaa136e52012-12-04 03:26:05 -08003650 mask = 0;
3651 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3652 for (i = 0; i < num_reg_temp; i++) {
3653 if (reg_temp[i] == 0)
3654 continue;
3655
3656 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3657 if (!src || (mask & (1 << src)))
3658 continue;
3659
3660 if (src >= data->temp_label_num ||
3661 !strlen(data->temp_label[src])) {
3662 dev_info(dev,
3663 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3664 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3665 continue;
3666 }
3667
3668 mask |= 1 << src;
3669
3670 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3671 if (src <= data->temp_fixed_num) {
3672 data->have_temp |= 1 << (src - 1);
3673 data->have_temp_fixed |= 1 << (src - 1);
3674 data->reg_temp[0][src - 1] = reg_temp[i];
3675 data->reg_temp[1][src - 1] = reg_temp_over[i];
3676 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
3677 data->reg_temp_config[src - 1] = reg_temp_config[i];
3678 data->temp_src[src - 1] = src;
3679 continue;
3680 }
3681
3682 if (s >= NUM_TEMP)
3683 continue;
3684
3685 /* Use dynamic index for other sources */
3686 data->have_temp |= 1 << s;
3687 data->reg_temp[0][s] = reg_temp[i];
3688 data->reg_temp[1][s] = reg_temp_over[i];
3689 data->reg_temp[2][s] = reg_temp_hyst[i];
3690 data->reg_temp_config[s] = reg_temp_config[i];
3691 if (reg_temp_crit[src - 1])
3692 data->reg_temp[3][s] = reg_temp_crit[src - 1];
3693
3694 data->temp_src[s] = src;
3695 s++;
3696 }
3697
3698#ifdef USE_ALTERNATE
3699 /*
3700 * Go through the list of alternate temp registers and enable
3701 * if possible.
3702 * The temperature is already monitored if the respective bit in <mask>
3703 * is set.
3704 */
3705 for (i = 0; i < data->temp_label_num - 1; i++) {
3706 if (!reg_temp_alternate[i])
3707 continue;
3708 if (mask & (1 << (i + 1)))
3709 continue;
3710 if (i < data->temp_fixed_num) {
3711 if (data->have_temp & (1 << i))
3712 continue;
3713 data->have_temp |= 1 << i;
3714 data->have_temp_fixed |= 1 << i;
3715 data->reg_temp[0][i] = reg_temp_alternate[i];
3716 data->reg_temp[1][i] = reg_temp_over[i];
3717 data->reg_temp[2][i] = reg_temp_hyst[i];
3718 data->temp_src[i] = i + 1;
3719 continue;
3720 }
3721
3722 if (s >= NUM_TEMP) /* Abort if no more space */
3723 break;
3724
3725 data->have_temp |= 1 << s;
3726 data->reg_temp[0][s] = reg_temp_alternate[i];
3727 data->temp_src[s] = i + 1;
3728 s++;
3729 }
3730#endif /* USE_ALTERNATE */
3731
3732 switch (data->kind) {
3733 case nct6775:
3734 break;
3735 case nct6776:
3736 /*
3737 * On NCT6776, AUXTIN and VIN3 pins are shared.
3738 * Only way to detect it is to check if AUXTIN is used
3739 * as a temperature source, and if that source is
3740 * enabled.
3741 *
3742 * If that is the case, disable in6, which reports VIN3.
3743 * Otherwise disable temp3.
3744 */
3745 if (data->have_temp & (1 << 2)) {
3746 u8 reg = nct6775_read_value(data,
3747 data->reg_temp_config[2]);
3748 if (reg & 0x01)
3749 data->have_temp &= ~(1 << 2);
3750 else
3751 data->have_in &= ~(1 << 6);
3752 }
3753 break;
3754 case nct6779:
3755 /*
3756 * Shared pins:
3757 * VIN4 / AUXTIN0
3758 * VIN5 / AUXTIN1
3759 * VIN6 / AUXTIN2
3760 * VIN7 / AUXTIN3
3761 *
3762 * There does not seem to be a clean way to detect if VINx or
3763 * AUXTINx is active, so for keep both sensor types enabled
3764 * for now.
3765 */
3766 break;
3767 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003768
3769 /* Initialize the chip */
3770 nct6775_init_device(data);
3771
3772 data->vrm = vid_which_vrm();
3773 err = superio_enter(sio_data->sioreg);
3774 if (err)
3775 return err;
3776
3777 /*
3778 * Read VID value
3779 * We can get the VID input values directly at logical device D 0xe3.
3780 */
3781 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3782 data->vid = superio_inb(sio_data->sioreg, 0xe3);
Guenter Roeck47ece962012-12-04 07:59:32 -08003783
3784 if (fan_debounce) {
3785 u8 tmp;
3786
3787 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3788 tmp = superio_inb(sio_data->sioreg,
3789 NCT6775_REG_CR_FAN_DEBOUNCE);
3790 switch (data->kind) {
3791 case nct6775:
3792 tmp |= 0x1e;
3793 break;
3794 case nct6776:
3795 case nct6779:
3796 tmp |= 0x3e;
3797 break;
3798 }
3799 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3800 tmp);
3801 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3802 data->name);
3803 }
3804
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003805 superio_exit(sio_data->sioreg);
3806
3807 err = device_create_file(dev, &dev_attr_cpu0_vid);
3808 if (err)
3809 return err;
3810
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003811 err = nct6775_check_fan_inputs(sio_data, data);
3812 if (err)
3813 goto exit_remove;
3814
3815 /* Read fan clock dividers immediately */
3816 nct6775_init_fan_common(dev, data);
3817
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003818 /* Register sysfs hooks */
3819 for (i = 0; i < data->pwm_num; i++) {
3820 if (!(data->has_pwm & (1 << i)))
3821 continue;
3822
3823 err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]);
3824 if (err)
3825 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003826
3827 if (data->REG_PWM[3]) {
3828 err = device_create_file(dev,
3829 &sda_pwm_max[i].dev_attr);
3830 if (err)
3831 goto exit_remove;
3832 }
3833 if (data->REG_PWM[4]) {
3834 err = device_create_file(dev,
3835 &sda_pwm_step[i].dev_attr);
3836 if (err)
3837 goto exit_remove;
3838 }
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003839 if (data->REG_PWM[6]) {
3840 err = device_create_file(dev,
3841 &sda_weight_duty_base[i].dev_attr);
3842 if (err)
3843 goto exit_remove;
3844 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003845 }
3846 for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) {
3847 struct sensor_device_attribute_2 *attr =
3848 &sda_auto_pwm_arrays[i];
3849
3850 if (!(data->has_pwm & (1 << attr->nr)))
3851 continue;
3852 if (attr->index > data->auto_pwm_num)
3853 continue;
3854 err = device_create_file(dev, &attr->dev_attr);
3855 if (err)
3856 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003857 }
3858
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003859 for (i = 0; i < data->in_num; i++) {
3860 if (!(data->have_in & (1 << i)))
3861 continue;
3862 err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]);
3863 if (err)
3864 goto exit_remove;
3865 }
3866
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003867 for (i = 0; i < 5; i++) {
3868 if (data->has_fan & (1 << i)) {
3869 err = device_create_file(dev,
3870 &sda_fan_input[i].dev_attr);
3871 if (err)
3872 goto exit_remove;
3873 err = device_create_file(dev,
3874 &sda_fan_alarm[i].dev_attr);
3875 if (err)
3876 goto exit_remove;
3877 if (data->kind != nct6776 &&
3878 data->kind != nct6779) {
3879 err = device_create_file(dev,
3880 &sda_fan_div[i].dev_attr);
3881 if (err)
3882 goto exit_remove;
3883 }
3884 if (data->has_fan_min & (1 << i)) {
3885 err = device_create_file(dev,
3886 &sda_fan_min[i].dev_attr);
3887 if (err)
3888 goto exit_remove;
3889 }
Guenter Roeck5c25d952012-12-11 07:29:06 -08003890 err = device_create_file(dev,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003891 &sda_fan_pulses[i].dev_attr);
Guenter Roeck5c25d952012-12-11 07:29:06 -08003892 if (err)
3893 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003894 }
3895 }
3896
Guenter Roeckaa136e52012-12-04 03:26:05 -08003897 for (i = 0; i < NUM_TEMP; i++) {
3898 if (!(data->have_temp & (1 << i)))
3899 continue;
3900 err = device_create_file(dev, &sda_temp_input[i].dev_attr);
3901 if (err)
3902 goto exit_remove;
3903 if (data->temp_label) {
3904 err = device_create_file(dev,
3905 &sda_temp_label[i].dev_attr);
3906 if (err)
3907 goto exit_remove;
3908 }
3909 if (data->reg_temp[1][i]) {
3910 err = device_create_file(dev,
3911 &sda_temp_max[i].dev_attr);
3912 if (err)
3913 goto exit_remove;
3914 }
3915 if (data->reg_temp[2][i]) {
3916 err = device_create_file(dev,
3917 &sda_temp_max_hyst[i].dev_attr);
3918 if (err)
3919 goto exit_remove;
3920 }
3921 if (data->reg_temp[3][i]) {
3922 err = device_create_file(dev,
3923 &sda_temp_crit[i].dev_attr);
3924 if (err)
3925 goto exit_remove;
3926 }
3927 if (!(data->have_temp_fixed & (1 << i)))
3928 continue;
3929 err = device_create_file(dev, &sda_temp_type[i].dev_attr);
3930 if (err)
3931 goto exit_remove;
3932 err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
3933 if (err)
3934 goto exit_remove;
3935 if (i >= NUM_TEMP_ALARM ||
3936 data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0)
3937 continue;
3938 err = device_create_file(dev, &sda_temp_alarm[i].dev_attr);
3939 if (err)
3940 goto exit_remove;
3941 }
3942
Guenter Roecka6bd5872012-12-04 03:13:34 -08003943 for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
3944 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0)
3945 continue;
3946 err = device_create_file(dev, &sda_caseopen[i].dev_attr);
3947 if (err)
3948 goto exit_remove;
3949 }
3950
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003951 err = device_create_file(dev, &dev_attr_name);
3952 if (err)
3953 goto exit_remove;
3954
3955 data->hwmon_dev = hwmon_device_register(dev);
3956 if (IS_ERR(data->hwmon_dev)) {
3957 err = PTR_ERR(data->hwmon_dev);
3958 goto exit_remove;
3959 }
3960
3961 return 0;
3962
3963exit_remove:
3964 nct6775_device_remove_files(dev);
3965 return err;
3966}
3967
3968static int nct6775_remove(struct platform_device *pdev)
3969{
3970 struct nct6775_data *data = platform_get_drvdata(pdev);
3971
3972 hwmon_device_unregister(data->hwmon_dev);
3973 nct6775_device_remove_files(&pdev->dev);
3974
3975 return 0;
3976}
3977
Guenter Roeck84d19d92012-12-04 08:01:39 -08003978#ifdef CONFIG_PM
3979static int nct6775_suspend(struct device *dev)
3980{
3981 struct nct6775_data *data = nct6775_update_device(dev);
3982 struct nct6775_sio_data *sio_data = dev->platform_data;
3983
3984 mutex_lock(&data->update_lock);
3985 data->vbat = nct6775_read_value(data, data->REG_VBAT);
3986 if (sio_data->kind == nct6775) {
3987 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3988 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3989 }
3990 mutex_unlock(&data->update_lock);
3991
3992 return 0;
3993}
3994
3995static int nct6775_resume(struct device *dev)
3996{
3997 struct nct6775_data *data = dev_get_drvdata(dev);
3998 struct nct6775_sio_data *sio_data = dev->platform_data;
3999 int i, j;
4000
4001 mutex_lock(&data->update_lock);
4002 data->bank = 0xff; /* Force initial bank selection */
4003
4004 /* Restore limits */
4005 for (i = 0; i < data->in_num; i++) {
4006 if (!(data->have_in & (1 << i)))
4007 continue;
4008
4009 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
4010 data->in[i][1]);
4011 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
4012 data->in[i][2]);
4013 }
4014
4015 for (i = 0; i < 5; i++) {
4016 if (!(data->has_fan_min & (1 << i)))
4017 continue;
4018
4019 nct6775_write_value(data, data->REG_FAN_MIN[i],
4020 data->fan_min[i]);
4021 }
4022
4023 for (i = 0; i < NUM_TEMP; i++) {
4024 if (!(data->have_temp & (1 << i)))
4025 continue;
4026
4027 for (j = 1; j < 4; j++)
4028 if (data->reg_temp[j][i])
4029 nct6775_write_temp(data, data->reg_temp[j][i],
4030 data->temp[j][i]);
4031 }
4032
4033 /* Restore other settings */
4034 nct6775_write_value(data, data->REG_VBAT, data->vbat);
4035 if (sio_data->kind == nct6775) {
4036 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
4037 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
4038 }
4039
4040 /* Force re-reading all values */
4041 data->valid = false;
4042 mutex_unlock(&data->update_lock);
4043
4044 return 0;
4045}
4046
4047static const struct dev_pm_ops nct6775_dev_pm_ops = {
4048 .suspend = nct6775_suspend,
4049 .resume = nct6775_resume,
4050};
4051
4052#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4053#else
4054#define NCT6775_DEV_PM_OPS NULL
4055#endif /* CONFIG_PM */
4056
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004057static struct platform_driver nct6775_driver = {
4058 .driver = {
4059 .owner = THIS_MODULE,
4060 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004061 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004062 },
4063 .probe = nct6775_probe,
4064 .remove = nct6775_remove,
4065};
4066
4067/* nct6775_find() looks for a '627 in the Super-I/O config space */
4068static int __init nct6775_find(int sioaddr, unsigned short *addr,
4069 struct nct6775_sio_data *sio_data)
4070{
4071 static const char sio_name_NCT6775[] __initconst = "NCT6775F";
4072 static const char sio_name_NCT6776[] __initconst = "NCT6776F";
4073 static const char sio_name_NCT6779[] __initconst = "NCT6779D";
4074
4075 u16 val;
4076 const char *sio_name;
4077 int err;
4078
4079 err = superio_enter(sioaddr);
4080 if (err)
4081 return err;
4082
4083 if (force_id)
4084 val = force_id;
4085 else
4086 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4087 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4088 switch (val & SIO_ID_MASK) {
4089 case SIO_NCT6775_ID:
4090 sio_data->kind = nct6775;
4091 sio_name = sio_name_NCT6775;
4092 break;
4093 case SIO_NCT6776_ID:
4094 sio_data->kind = nct6776;
4095 sio_name = sio_name_NCT6776;
4096 break;
4097 case SIO_NCT6779_ID:
4098 sio_data->kind = nct6779;
4099 sio_name = sio_name_NCT6779;
4100 break;
4101 default:
4102 if (val != 0xffff)
4103 pr_debug("unsupported chip ID: 0x%04x\n", val);
4104 superio_exit(sioaddr);
4105 return -ENODEV;
4106 }
4107
4108 /* We have a known chip, find the HWM I/O address */
4109 superio_select(sioaddr, NCT6775_LD_HWM);
4110 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4111 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
4112 *addr = val & IOREGION_ALIGNMENT;
4113 if (*addr == 0) {
4114 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4115 superio_exit(sioaddr);
4116 return -ENODEV;
4117 }
4118
4119 /* Activate logical device if needed */
4120 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4121 if (!(val & 0x01)) {
4122 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4123 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4124 }
4125
4126 superio_exit(sioaddr);
4127 pr_info("Found %s chip at %#x\n", sio_name, *addr);
4128 sio_data->sioreg = sioaddr;
4129
4130 return 0;
4131}
4132
4133/*
4134 * when Super-I/O functions move to a separate file, the Super-I/O
4135 * bus will manage the lifetime of the device and this module will only keep
4136 * track of the nct6775 driver. But since we platform_device_alloc(), we
4137 * must keep track of the device
4138 */
4139static struct platform_device *pdev;
4140
4141static int __init sensors_nct6775_init(void)
4142{
4143 int err;
4144 unsigned short address;
4145 struct resource res;
4146 struct nct6775_sio_data sio_data;
4147
4148 /*
4149 * initialize sio_data->kind and sio_data->sioreg.
4150 *
4151 * when Super-I/O functions move to a separate file, the Super-I/O
4152 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4153 * nct6775 hardware monitor, and call probe()
4154 */
4155 if (nct6775_find(0x2e, &address, &sio_data) &&
4156 nct6775_find(0x4e, &address, &sio_data))
4157 return -ENODEV;
4158
4159 err = platform_driver_register(&nct6775_driver);
4160 if (err)
4161 goto exit;
4162
4163 pdev = platform_device_alloc(DRVNAME, address);
4164 if (!pdev) {
4165 err = -ENOMEM;
4166 pr_err("Device allocation failed\n");
4167 goto exit_unregister;
4168 }
4169
4170 err = platform_device_add_data(pdev, &sio_data,
4171 sizeof(struct nct6775_sio_data));
4172 if (err) {
4173 pr_err("Platform data allocation failed\n");
4174 goto exit_device_put;
4175 }
4176
4177 memset(&res, 0, sizeof(res));
4178 res.name = DRVNAME;
4179 res.start = address + IOREGION_OFFSET;
4180 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4181 res.flags = IORESOURCE_IO;
4182
4183 err = acpi_check_resource_conflict(&res);
4184 if (err)
4185 goto exit_device_put;
4186
4187 err = platform_device_add_resources(pdev, &res, 1);
4188 if (err) {
4189 pr_err("Device resource addition failed (%d)\n", err);
4190 goto exit_device_put;
4191 }
4192
4193 /* platform_device_add calls probe() */
4194 err = platform_device_add(pdev);
4195 if (err) {
4196 pr_err("Device addition failed (%d)\n", err);
4197 goto exit_device_put;
4198 }
4199
4200 return 0;
4201
4202exit_device_put:
4203 platform_device_put(pdev);
4204exit_unregister:
4205 platform_driver_unregister(&nct6775_driver);
4206exit:
4207 return err;
4208}
4209
4210static void __exit sensors_nct6775_exit(void)
4211{
4212 platform_device_unregister(pdev);
4213 platform_driver_unregister(&nct6775_driver);
4214}
4215
4216MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4217MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4218MODULE_LICENSE("GPL");
4219
4220module_init(sensors_nct6775_init);
4221module_exit(sensors_nct6775_exit);