blob: 6eb03ce2cff4b46a910787f8a7954bf5d00c6f99 [file] [log] [blame]
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001/*
2 * nct6775 - Driver for the hardware monitoring functionality of
3 * Nuvoton NCT677x Super-I/O chips
4 *
5 * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
6 *
7 * Derived from w83627ehf driver
8 * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org>
9 * Copyright (C) 2006 Yuan Mu (Winbond),
10 * Rudolf Marek <r.marek@assembler.cz>
11 * David Hubbard <david.c.hubbard@gmail.com>
12 * Daniel J Blueman <daniel.blueman@gmail.com>
13 * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
14 *
15 * Shamelessly ripped from the w83627hf driver
16 * Copyright (C) 2003 Mark Studebaker
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 *
33 * Supports the following chips:
34 *
35 * Chip #vin #fan #pwm #temp chip IDs man ID
Guenter Roeck6c009502012-07-01 08:23:15 -070036 * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070037 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
David Bartley578ab5f2013-06-24 22:28:28 -070040 * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070041 *
42 * #temp lists the number of monitored temperature sources (first value) plus
43 * the number of directly connectable temperature sensors (second value).
44 */
45
46#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
47
48#include <linux/module.h>
49#include <linux/init.h>
50#include <linux/slab.h>
51#include <linux/jiffies.h>
52#include <linux/platform_device.h>
53#include <linux/hwmon.h>
54#include <linux/hwmon-sysfs.h>
55#include <linux/hwmon-vid.h>
56#include <linux/err.h>
57#include <linux/mutex.h>
58#include <linux/acpi.h>
59#include <linux/io.h>
60#include "lm75.h"
61
Guenter Roeckaa136e52012-12-04 03:26:05 -080062#define USE_ALTERNATE
63
David Bartley578ab5f2013-06-24 22:28:28 -070064enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791 };
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070065
66/* used to set data->name = nct6775_device_names[data->sio_kind] */
67static const char * const nct6775_device_names[] = {
Guenter Roeck6c009502012-07-01 08:23:15 -070068 "nct6106",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070069 "nct6775",
70 "nct6776",
71 "nct6779",
David Bartley578ab5f2013-06-24 22:28:28 -070072 "nct6791",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070073};
74
75static unsigned short force_id;
76module_param(force_id, ushort, 0);
77MODULE_PARM_DESC(force_id, "Override the detected device ID");
78
Guenter Roeck47ece962012-12-04 07:59:32 -080079static unsigned short fan_debounce;
80module_param(fan_debounce, ushort, 0);
81MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
82
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070083#define DRVNAME "nct6775"
84
85/*
86 * Super-I/O constants and functions
87 */
88
Guenter Roecka6bd5872012-12-04 03:13:34 -080089#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070090#define NCT6775_LD_HWM 0x0b
91#define NCT6775_LD_VID 0x0d
92
93#define SIO_REG_LDSEL 0x07 /* Logical device select */
94#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
95#define SIO_REG_ENABLE 0x30 /* Logical device enable */
96#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
97
Guenter Roeck6c009502012-07-01 08:23:15 -070098#define SIO_NCT6106_ID 0xc450
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070099#define SIO_NCT6775_ID 0xb470
100#define SIO_NCT6776_ID 0xc330
101#define SIO_NCT6779_ID 0xc560
David Bartley578ab5f2013-06-24 22:28:28 -0700102#define SIO_NCT6791_ID 0xc800
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700103#define SIO_ID_MASK 0xFFF0
104
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800105enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
106
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700107static inline void
108superio_outb(int ioreg, int reg, int val)
109{
110 outb(reg, ioreg);
111 outb(val, ioreg + 1);
112}
113
114static inline int
115superio_inb(int ioreg, int reg)
116{
117 outb(reg, ioreg);
118 return inb(ioreg + 1);
119}
120
121static inline void
122superio_select(int ioreg, int ld)
123{
124 outb(SIO_REG_LDSEL, ioreg);
125 outb(ld, ioreg + 1);
126}
127
128static inline int
129superio_enter(int ioreg)
130{
131 /*
132 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
133 */
134 if (!request_muxed_region(ioreg, 2, DRVNAME))
135 return -EBUSY;
136
137 outb(0x87, ioreg);
138 outb(0x87, ioreg);
139
140 return 0;
141}
142
143static inline void
144superio_exit(int ioreg)
145{
146 outb(0xaa, ioreg);
147 outb(0x02, ioreg);
148 outb(0x02, ioreg + 1);
149 release_region(ioreg, 2);
150}
151
152/*
153 * ISA constants
154 */
155
156#define IOREGION_ALIGNMENT (~7)
157#define IOREGION_OFFSET 5
158#define IOREGION_LENGTH 2
159#define ADDR_REG_OFFSET 0
160#define DATA_REG_OFFSET 1
161
162#define NCT6775_REG_BANK 0x4E
163#define NCT6775_REG_CONFIG 0x40
164
165/*
166 * Not currently used:
167 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
168 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
169 * REG_MAN_ID is at port 0x4f
170 * REG_CHIP_ID is at port 0x58
171 */
172
Guenter Roeckaa136e52012-12-04 03:26:05 -0800173#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
174#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
175
Guenter Roeck6c009502012-07-01 08:23:15 -0700176#define NUM_REG_ALARM 7 /* Max number of alarm registers */
Guenter Roeck30846992013-06-24 22:21:59 -0700177#define NUM_REG_BEEP 5 /* Max number of beep registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700178
David Bartley578ab5f2013-06-24 22:28:28 -0700179#define NUM_FAN 6
180
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700181/* Common and NCT6775 specific data */
182
183/* Voltage min/max registers for nr=7..14 are in bank 5 */
184
185static const u16 NCT6775_REG_IN_MAX[] = {
186 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
187 0x55c, 0x55e, 0x560, 0x562 };
188static const u16 NCT6775_REG_IN_MIN[] = {
189 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
190 0x55d, 0x55f, 0x561, 0x563 };
191static const u16 NCT6775_REG_IN[] = {
192 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
193};
194
195#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800196#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700197#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700198
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800199#define NCT6775_REG_FANDIV1 0x506
200#define NCT6775_REG_FANDIV2 0x507
201
Guenter Roeck47ece962012-12-04 07:59:32 -0800202#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
203
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700204static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
205
Guenter Roeck30846992013-06-24 22:21:59 -0700206/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700207
208static const s8 NCT6775_ALARM_BITS[] = {
209 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
210 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
211 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700212 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700213 -1, -1, -1, /* unused */
214 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
215 12, -1 }; /* intrusion0, intrusion1 */
216
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800217#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800218#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800219#define INTRUSION_ALARM_BASE 30
220
Guenter Roeck30846992013-06-24 22:21:59 -0700221static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
222
223/*
224 * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
225 * 30..31 intrusion
226 */
227static const s8 NCT6775_BEEP_BITS[] = {
228 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
229 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
230 21, /* global beep enable */
231 6, 7, 11, 28, -1, /* fan1..fan5 */
232 -1, -1, -1, /* unused */
233 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
234 12, -1 }; /* intrusion0, intrusion1 */
235
236#define BEEP_ENABLE_BASE 15
237
Guenter Roecka6bd5872012-12-04 03:13:34 -0800238static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
239static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
240
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800241/* DC or PWM output fan configuration */
242static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
243static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
244
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800245/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800246
David Bartley578ab5f2013-06-24 22:28:28 -0700247static const u16 NCT6775_REG_TARGET[] = {
248 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
249static const u16 NCT6775_REG_FAN_MODE[] = {
250 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800251static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700252 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800253static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700254 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800255static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700256 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
257static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
258 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800259static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
260static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
261
262static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700263 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
264static const u16 NCT6775_REG_PWM[] = {
265 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
266static const u16 NCT6775_REG_PWM_READ[] = {
267 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800268
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800269static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
270static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800271static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
David Bartley578ab5f2013-06-24 22:28:28 -0700272static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800273
Guenter Roeckaa136e52012-12-04 03:26:05 -0800274static const u16 NCT6775_REG_TEMP[] = {
275 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
276
277static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
278 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
279static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
280 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
281static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
282 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
283
284static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
285 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
286
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800287static const u16 NCT6775_REG_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700288 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800289
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800290static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700291 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800292static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700293 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800294static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700295 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800296static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700297 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800298static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700299 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800300
Guenter Roeckaa136e52012-12-04 03:26:05 -0800301static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
302
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800303static const u16 NCT6775_REG_AUTO_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700304 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800305static const u16 NCT6775_REG_AUTO_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700306 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800307
308#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
309#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
310
311static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
312
313static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700314 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800315static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700316 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800317
Guenter Roeckaa136e52012-12-04 03:26:05 -0800318static const char *const nct6775_temp_label[] = {
319 "",
320 "SYSTIN",
321 "CPUTIN",
322 "AUXTIN",
323 "AMD SB-TSI",
324 "PECI Agent 0",
325 "PECI Agent 1",
326 "PECI Agent 2",
327 "PECI Agent 3",
328 "PECI Agent 4",
329 "PECI Agent 5",
330 "PECI Agent 6",
331 "PECI Agent 7",
332 "PCH_CHIP_CPU_MAX_TEMP",
333 "PCH_CHIP_TEMP",
334 "PCH_CPU_TEMP",
335 "PCH_MCH_TEMP",
336 "PCH_DIM0_TEMP",
337 "PCH_DIM1_TEMP",
338 "PCH_DIM2_TEMP",
339 "PCH_DIM3_TEMP"
340};
341
342static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
343 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
344
345static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
346 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
347 0xa07 };
348
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700349/* NCT6776 specific data */
350
351static const s8 NCT6776_ALARM_BITS[] = {
352 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
353 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
354 -1, /* unused */
355 6, 7, 11, 10, 23, /* fan1..fan5 */
356 -1, -1, -1, /* unused */
357 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
358 12, 9 }; /* intrusion0, intrusion1 */
359
Guenter Roeck30846992013-06-24 22:21:59 -0700360static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
361
362static const s8 NCT6776_BEEP_BITS[] = {
363 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
364 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
365 24, /* global beep enable */
366 25, 26, 27, 28, 29, /* fan1..fan5 */
367 -1, -1, -1, /* unused */
368 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
369 30, 31 }; /* intrusion0, intrusion1 */
370
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800371static const u16 NCT6776_REG_TOLERANCE_H[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700372 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800373
David Bartley578ab5f2013-06-24 22:28:28 -0700374static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
375static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800376
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800377static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800378static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800379
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800380static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700381 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800382
Guenter Roeckaa136e52012-12-04 03:26:05 -0800383static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
384 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
385
386static const char *const nct6776_temp_label[] = {
387 "",
388 "SYSTIN",
389 "CPUTIN",
390 "AUXTIN",
391 "SMBUSMASTER 0",
392 "SMBUSMASTER 1",
393 "SMBUSMASTER 2",
394 "SMBUSMASTER 3",
395 "SMBUSMASTER 4",
396 "SMBUSMASTER 5",
397 "SMBUSMASTER 6",
398 "SMBUSMASTER 7",
399 "PECI Agent 0",
400 "PECI Agent 1",
401 "PCH_CHIP_CPU_MAX_TEMP",
402 "PCH_CHIP_TEMP",
403 "PCH_CPU_TEMP",
404 "PCH_MCH_TEMP",
405 "PCH_DIM0_TEMP",
406 "PCH_DIM1_TEMP",
407 "PCH_DIM2_TEMP",
408 "PCH_DIM3_TEMP",
409 "BYTE_TEMP"
410};
411
412static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
413 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
414
415static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
416 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
417
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700418/* NCT6779 specific data */
419
420static const u16 NCT6779_REG_IN[] = {
421 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
422 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
423
424static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
425 0x459, 0x45A, 0x45B, 0x568 };
426
427static const s8 NCT6779_ALARM_BITS[] = {
428 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
429 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
430 -1, /* unused */
431 6, 7, 11, 10, 23, /* fan1..fan5 */
432 -1, -1, -1, /* unused */
433 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
434 12, 9 }; /* intrusion0, intrusion1 */
435
Guenter Roeck30846992013-06-24 22:21:59 -0700436static const s8 NCT6779_BEEP_BITS[] = {
437 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
438 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
439 24, /* global beep enable */
440 25, 26, 27, 28, 29, /* fan1..fan5 */
441 -1, -1, -1, /* unused */
442 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
443 30, 31 }; /* intrusion0, intrusion1 */
444
David Bartley578ab5f2013-06-24 22:28:28 -0700445static const u16 NCT6779_REG_FAN[] = {
446 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800447static const u16 NCT6779_REG_FAN_PULSES[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700448 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800449
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800450static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700451 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700452#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800453static const u16 NCT6779_REG_CRITICAL_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700454 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800455
Guenter Roeckaa136e52012-12-04 03:26:05 -0800456static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
457static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
458 0x18, 0x152 };
459static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
460 0x3a, 0x153 };
461static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
462 0x39, 0x155 };
463
464static const u16 NCT6779_REG_TEMP_OFFSET[] = {
465 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
466
467static const char *const nct6779_temp_label[] = {
468 "",
469 "SYSTIN",
470 "CPUTIN",
471 "AUXTIN0",
472 "AUXTIN1",
473 "AUXTIN2",
474 "AUXTIN3",
475 "",
476 "SMBUSMASTER 0",
477 "SMBUSMASTER 1",
478 "SMBUSMASTER 2",
479 "SMBUSMASTER 3",
480 "SMBUSMASTER 4",
481 "SMBUSMASTER 5",
482 "SMBUSMASTER 6",
483 "SMBUSMASTER 7",
484 "PECI Agent 0",
485 "PECI Agent 1",
486 "PCH_CHIP_CPU_MAX_TEMP",
487 "PCH_CHIP_TEMP",
488 "PCH_CPU_TEMP",
489 "PCH_MCH_TEMP",
490 "PCH_DIM0_TEMP",
491 "PCH_DIM1_TEMP",
492 "PCH_DIM2_TEMP",
493 "PCH_DIM3_TEMP",
494 "BYTE_TEMP"
495};
496
497static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
498 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
499 0, 0, 0, 0, 0, 0, 0, 0,
500 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
501 0x408, 0 };
502
503static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
504 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
505
David Bartley578ab5f2013-06-24 22:28:28 -0700506/* NCT6791 specific data */
507
508#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
509
510static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
511 0x459, 0x45A, 0x45B, 0x568, 0x45D };
512
513static const s8 NCT6791_ALARM_BITS[] = {
514 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
515 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
516 -1, /* unused */
517 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
518 -1, -1, /* unused */
519 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
520 12, 9 }; /* intrusion0, intrusion1 */
521
522
Guenter Roeck6c009502012-07-01 08:23:15 -0700523/* NCT6102D/NCT6106D specific data */
524
525#define NCT6106_REG_VBAT 0x318
526#define NCT6106_REG_DIODE 0x319
527#define NCT6106_DIODE_MASK 0x01
528
529static const u16 NCT6106_REG_IN_MAX[] = {
530 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
531static const u16 NCT6106_REG_IN_MIN[] = {
532 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
533static const u16 NCT6106_REG_IN[] = {
534 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
535
536static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
537static const u16 NCT6106_REG_TEMP_HYST[] = {
538 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
539static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700540 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
541static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
542 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
543static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
544 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700545static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
546static const u16 NCT6106_REG_TEMP_CONFIG[] = {
547 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
548
549static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
550static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
551static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
552static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
553
554static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
555static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
556static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
557static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
558static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
559static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
560static const u16 NCT6106_REG_TEMP_SOURCE[] = {
561 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
562
563static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
564static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
565 0x11b, 0x12b, 0x13b };
566
567static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
568#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
569static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
570
571static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
572static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
573static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
574static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
575static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
576static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
577
578static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
579
580static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
581static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
582static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
583static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
584static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
585static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
586
587static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
588static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
589
590static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
591 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
592
593static const s8 NCT6106_ALARM_BITS[] = {
594 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
595 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
596 -1, /* unused */
597 32, 33, 34, -1, -1, /* fan1..fan5 */
598 -1, -1, -1, /* unused */
599 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
600 48, -1 /* intrusion0, intrusion1 */
601};
602
Guenter Roeck30846992013-06-24 22:21:59 -0700603static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
604 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
605
606static const s8 NCT6106_BEEP_BITS[] = {
607 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
608 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
609 32, /* global beep enable */
610 24, 25, 26, 27, 28, /* fan1..fan5 */
611 -1, -1, -1, /* unused */
612 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
613 34, -1 /* intrusion0, intrusion1 */
614};
615
Guenter Roeck6c009502012-07-01 08:23:15 -0700616static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
617 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
618
619static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
620 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
621
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800622static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
623{
624 if (mode == 0 && pwm == 255)
625 return off;
626 return mode + 1;
627}
628
629static int pwm_enable_to_reg(enum pwm_enable mode)
630{
631 if (mode == off)
632 return 0;
633 return mode - 1;
634}
635
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700636/*
637 * Conversions
638 */
639
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800640/* 1 is DC mode, output in ms */
641static unsigned int step_time_from_reg(u8 reg, u8 mode)
642{
643 return mode ? 400 * reg : 100 * reg;
644}
645
646static u8 step_time_to_reg(unsigned int msec, u8 mode)
647{
648 return clamp_val((mode ? (msec + 200) / 400 :
649 (msec + 50) / 100), 1, 255);
650}
651
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800652static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
653{
654 if (reg == 0 || reg == 255)
655 return 0;
656 return 1350000U / (reg << divreg);
657}
658
659static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
660{
661 if ((reg & 0xff1f) == 0xff1f)
662 return 0;
663
664 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
665
666 if (reg == 0)
667 return 0;
668
669 return 1350000U / reg;
670}
671
672static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
673{
674 if (reg == 0 || reg == 0xffff)
675 return 0;
676
677 /*
678 * Even though the registers are 16 bit wide, the fan divisor
679 * still applies.
680 */
681 return 1350000U / (reg << divreg);
682}
683
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800684static u16 fan_to_reg(u32 fan, unsigned int divreg)
685{
686 if (!fan)
687 return 0;
688
689 return (1350000U / fan) >> divreg;
690}
691
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800692static inline unsigned int
693div_from_reg(u8 reg)
694{
695 return 1 << reg;
696}
697
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700698/*
699 * Some of the voltage inputs have internal scaling, the tables below
700 * contain 8 (the ADC LSB in mV) * scaling factor * 100
701 */
702static const u16 scale_in[15] = {
703 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
704 800, 800
705};
706
707static inline long in_from_reg(u8 reg, u8 nr)
708{
709 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
710}
711
712static inline u8 in_to_reg(u32 val, u8 nr)
713{
714 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
715}
716
717/*
718 * Data structures and manipulation thereof
719 */
720
721struct nct6775_data {
722 int addr; /* IO base of hw monitor block */
Guenter Roeckdf612d52013-07-08 13:15:04 -0700723 int sioreg; /* SIO register address */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700724 enum kinds kind;
725 const char *name;
726
727 struct device *hwmon_dev;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700728 struct attribute_group *group_in;
729 struct attribute_group *group_fan;
730 struct attribute_group *group_temp;
731 struct attribute_group *group_pwm;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700732
Guenter Roeckb7a61352013-04-02 22:14:06 -0700733 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
734 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800735 */
736 u8 temp_src[NUM_TEMP];
737 u16 reg_temp_config[NUM_TEMP];
738 const char * const *temp_label;
739 int temp_label_num;
740
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700741 u16 REG_CONFIG;
742 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800743 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700744 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700745
746 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700747 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700748
749 const u16 *REG_VIN;
750 const u16 *REG_IN_MINMAX[2];
751
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800752 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800753 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800754 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800755 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800756 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700757 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800758 const u16 *REG_FAN_TIME[3];
759
760 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800761
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800762 const u8 *REG_PWM_MODE;
763 const u8 *PWM_MODE_MASK;
764
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800765 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
766 * [3]=pwm_max, [4]=pwm_step,
767 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800768 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800769 const u16 *REG_PWM_READ;
770
Guenter Roeck6c009502012-07-01 08:23:15 -0700771 const u16 *REG_CRITICAL_PWM_ENABLE;
772 u8 CRITICAL_PWM_ENABLE_MASK;
773 const u16 *REG_CRITICAL_PWM;
774
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800775 const u16 *REG_AUTO_TEMP;
776 const u16 *REG_AUTO_PWM;
777
778 const u16 *REG_CRITICAL_TEMP;
779 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
780
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800781 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800782 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800783 const u16 *REG_WEIGHT_TEMP_SEL;
784 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
785
Guenter Roeckaa136e52012-12-04 03:26:05 -0800786 const u16 *REG_TEMP_OFFSET;
787
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700788 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700789 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700790
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800791 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
792 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
793
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700794 struct mutex update_lock;
795 bool valid; /* true if following fields are valid */
796 unsigned long last_updated; /* In jiffies */
797
798 /* Register values */
799 u8 bank; /* current register bank */
800 u8 in_num; /* number of in inputs we have */
801 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
David Bartley578ab5f2013-06-24 22:28:28 -0700802 unsigned int rpm[NUM_FAN];
803 u16 fan_min[NUM_FAN];
804 u8 fan_pulses[NUM_FAN];
805 u8 fan_div[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800806 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800807 u8 has_fan; /* some fan inputs can be disabled */
808 u8 has_fan_min; /* some fans don't have min register */
809 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700810
Guenter Roeck6c009502012-07-01 08:23:15 -0700811 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700812 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800813 u8 temp_fixed_num; /* 3 or 6 */
814 u8 temp_type[NUM_TEMP_FIXED];
815 s8 temp_offset[NUM_TEMP_FIXED];
Dan Carpenterf58876a2013-07-18 18:01:11 +0300816 s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
817 * 3=temp_crit, 4=temp_lcrit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700818 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700819 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700820
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800821 u8 pwm_num; /* number of pwm */
David Bartley578ab5f2013-06-24 22:28:28 -0700822 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
823 * 0->PWM variable duty cycle
824 */
825 enum pwm_enable pwm_enable[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800826 /* 0->off
827 * 1->manual
828 * 2->thermal cruise mode (also called SmartFan I)
829 * 3->fan speed cruise mode
830 * 4->SmartFan III
831 * 5->enhanced variable thermal cruise (SmartFan IV)
832 */
David Bartley578ab5f2013-06-24 22:28:28 -0700833 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
834 * [3]=pwm_max, [4]=pwm_step,
835 * [5]=weight_duty_step, [6]=weight_duty_base
836 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800837
David Bartley578ab5f2013-06-24 22:28:28 -0700838 u8 target_temp[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800839 u8 target_temp_mask;
David Bartley578ab5f2013-06-24 22:28:28 -0700840 u32 target_speed[NUM_FAN];
841 u32 target_speed_tolerance[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800842 u8 speed_tolerance_limit;
843
David Bartley578ab5f2013-06-24 22:28:28 -0700844 u8 temp_tolerance[2][NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800845 u8 tolerance_mask;
846
David Bartley578ab5f2013-06-24 22:28:28 -0700847 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800848
849 /* Automatic fan speed control registers */
850 int auto_pwm_num;
David Bartley578ab5f2013-06-24 22:28:28 -0700851 u8 auto_pwm[NUM_FAN][7];
852 u8 auto_temp[NUM_FAN][7];
853 u8 pwm_temp_sel[NUM_FAN];
854 u8 pwm_weight_temp_sel[NUM_FAN];
855 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
856 * 2->temp_base
857 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800858
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700859 u8 vid;
860 u8 vrm;
861
Guenter Roeckf73cf632013-03-18 09:22:50 -0700862 bool have_vid;
863
Guenter Roeckaa136e52012-12-04 03:26:05 -0800864 u16 have_temp;
865 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700866 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800867#ifdef CONFIG_PM
868 /* Remember extra register values over suspend/resume */
869 u8 vbat;
870 u8 fandiv1;
871 u8 fandiv2;
872#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700873};
874
875struct nct6775_sio_data {
876 int sioreg;
877 enum kinds kind;
878};
879
Guenter Roeckf73cf632013-03-18 09:22:50 -0700880struct sensor_device_template {
881 struct device_attribute dev_attr;
882 union {
883 struct {
884 u8 nr;
885 u8 index;
886 } s;
887 int index;
888 } u;
889 bool s2; /* true if both index and nr are used */
890};
891
892struct sensor_device_attr_u {
893 union {
894 struct sensor_device_attribute a1;
895 struct sensor_device_attribute_2 a2;
896 } u;
897 char name[32];
898};
899
900#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
901 .attr = {.name = _template, .mode = _mode }, \
902 .show = _show, \
903 .store = _store, \
904}
905
906#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
907 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
908 .u.index = _index, \
909 .s2 = false }
910
911#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
912 _nr, _index) \
913 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
914 .u.s.index = _index, \
915 .u.s.nr = _nr, \
916 .s2 = true }
917
918#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
919static struct sensor_device_template sensor_dev_template_##_name \
920 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
921 _index)
922
923#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
924 _nr, _index) \
925static struct sensor_device_template sensor_dev_template_##_name \
926 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
927 _nr, _index)
928
929struct sensor_template_group {
930 struct sensor_device_template **templates;
931 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
932 int base;
933};
934
935static struct attribute_group *
936nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
937 int repeat)
938{
939 struct attribute_group *group;
940 struct sensor_device_attr_u *su;
941 struct sensor_device_attribute *a;
942 struct sensor_device_attribute_2 *a2;
943 struct attribute **attrs;
944 struct sensor_device_template **t;
945 int err, i, j, count;
946
947 if (repeat <= 0)
948 return ERR_PTR(-EINVAL);
949
950 t = tg->templates;
951 for (count = 0; *t; t++, count++)
952 ;
953
954 if (count == 0)
955 return ERR_PTR(-EINVAL);
956
957 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
958 if (group == NULL)
959 return ERR_PTR(-ENOMEM);
960
961 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
962 GFP_KERNEL);
963 if (attrs == NULL)
964 return ERR_PTR(-ENOMEM);
965
966 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
967 GFP_KERNEL);
968 if (su == NULL)
969 return ERR_PTR(-ENOMEM);
970
971 group->attrs = attrs;
972 group->is_visible = tg->is_visible;
973
974 for (i = 0; i < repeat; i++) {
975 t = tg->templates;
976 for (j = 0; *t != NULL; j++) {
977 snprintf(su->name, sizeof(su->name),
978 (*t)->dev_attr.attr.name, tg->base + i);
979 if ((*t)->s2) {
980 a2 = &su->u.a2;
981 a2->dev_attr.attr.name = su->name;
982 a2->nr = (*t)->u.s.nr + i;
983 a2->index = (*t)->u.s.index;
984 a2->dev_attr.attr.mode =
985 (*t)->dev_attr.attr.mode;
986 a2->dev_attr.show = (*t)->dev_attr.show;
987 a2->dev_attr.store = (*t)->dev_attr.store;
988 *attrs = &a2->dev_attr.attr;
989 } else {
990 a = &su->u.a1;
991 a->dev_attr.attr.name = su->name;
992 a->index = (*t)->u.index + i;
993 a->dev_attr.attr.mode =
994 (*t)->dev_attr.attr.mode;
995 a->dev_attr.show = (*t)->dev_attr.show;
996 a->dev_attr.store = (*t)->dev_attr.store;
997 *attrs = &a->dev_attr.attr;
998 }
999 attrs++;
1000 su++;
1001 t++;
1002 }
1003 }
1004
1005 err = sysfs_create_group(&dev->kobj, group);
1006 if (err)
1007 return ERR_PTR(-ENOMEM);
1008
1009 return group;
1010}
1011
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001012static bool is_word_sized(struct nct6775_data *data, u16 reg)
1013{
1014 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07001015 case nct6106:
1016 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1017 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1018 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001019 case nct6775:
1020 return (((reg & 0xff00) == 0x100 ||
1021 (reg & 0xff00) == 0x200) &&
1022 ((reg & 0x00ff) == 0x50 ||
1023 (reg & 0x00ff) == 0x53 ||
1024 (reg & 0x00ff) == 0x55)) ||
1025 (reg & 0xfff0) == 0x630 ||
1026 reg == 0x640 || reg == 0x642 ||
1027 reg == 0x662 ||
1028 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1029 reg == 0x73 || reg == 0x75 || reg == 0x77;
1030 case nct6776:
1031 return (((reg & 0xff00) == 0x100 ||
1032 (reg & 0xff00) == 0x200) &&
1033 ((reg & 0x00ff) == 0x50 ||
1034 (reg & 0x00ff) == 0x53 ||
1035 (reg & 0x00ff) == 0x55)) ||
1036 (reg & 0xfff0) == 0x630 ||
1037 reg == 0x402 ||
1038 reg == 0x640 || reg == 0x642 ||
1039 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1040 reg == 0x73 || reg == 0x75 || reg == 0x77;
1041 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001042 case nct6791:
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001043 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
David Bartley578ab5f2013-06-24 22:28:28 -07001044 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001045 reg == 0x402 ||
1046 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1047 reg == 0x640 || reg == 0x642 ||
1048 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
1049 reg == 0x7b;
1050 }
1051 return false;
1052}
1053
1054/*
1055 * On older chips, only registers 0x50-0x5f are banked.
1056 * On more recent chips, all registers are banked.
1057 * Assume that is the case and set the bank number for each access.
1058 * Cache the bank number so it only needs to be set if it changes.
1059 */
1060static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1061{
1062 u8 bank = reg >> 8;
1063 if (data->bank != bank) {
1064 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1065 outb_p(bank, data->addr + DATA_REG_OFFSET);
1066 data->bank = bank;
1067 }
1068}
1069
1070static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1071{
1072 int res, word_sized = is_word_sized(data, reg);
1073
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001074 nct6775_set_bank(data, reg);
1075 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1076 res = inb_p(data->addr + DATA_REG_OFFSET);
1077 if (word_sized) {
1078 outb_p((reg & 0xff) + 1,
1079 data->addr + ADDR_REG_OFFSET);
1080 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1081 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001082 return res;
1083}
1084
1085static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1086{
1087 int word_sized = is_word_sized(data, reg);
1088
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001089 nct6775_set_bank(data, reg);
1090 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1091 if (word_sized) {
1092 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1093 outb_p((reg & 0xff) + 1,
1094 data->addr + ADDR_REG_OFFSET);
1095 }
1096 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001097 return 0;
1098}
1099
Guenter Roeckaa136e52012-12-04 03:26:05 -08001100/* We left-align 8-bit temperature values to make the code simpler */
1101static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1102{
1103 u16 res;
1104
1105 res = nct6775_read_value(data, reg);
1106 if (!is_word_sized(data, reg))
1107 res <<= 8;
1108
1109 return res;
1110}
1111
1112static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1113{
1114 if (!is_word_sized(data, reg))
1115 value >>= 8;
1116 return nct6775_write_value(data, reg, value);
1117}
1118
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001119/* This function assumes that the caller holds data->update_lock */
1120static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1121{
1122 u8 reg;
1123
1124 switch (nr) {
1125 case 0:
1126 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1127 | (data->fan_div[0] & 0x7);
1128 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1129 break;
1130 case 1:
1131 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1132 | ((data->fan_div[1] << 4) & 0x70);
1133 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1134 break;
1135 case 2:
1136 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1137 | (data->fan_div[2] & 0x7);
1138 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1139 break;
1140 case 3:
1141 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1142 | ((data->fan_div[3] << 4) & 0x70);
1143 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1144 break;
1145 }
1146}
1147
1148static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1149{
1150 if (data->kind == nct6775)
1151 nct6775_write_fan_div(data, nr);
1152}
1153
1154static void nct6775_update_fan_div(struct nct6775_data *data)
1155{
1156 u8 i;
1157
1158 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1159 data->fan_div[0] = i & 0x7;
1160 data->fan_div[1] = (i & 0x70) >> 4;
1161 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1162 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001163 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001164 data->fan_div[3] = (i & 0x70) >> 4;
1165}
1166
1167static void nct6775_update_fan_div_common(struct nct6775_data *data)
1168{
1169 if (data->kind == nct6775)
1170 nct6775_update_fan_div(data);
1171}
1172
1173static void nct6775_init_fan_div(struct nct6775_data *data)
1174{
1175 int i;
1176
1177 nct6775_update_fan_div_common(data);
1178 /*
1179 * For all fans, start with highest divider value if the divider
1180 * register is not initialized. This ensures that we get a
1181 * reading from the fan count register, even if it is not optimal.
1182 * We'll compute a better divider later on.
1183 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001184 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001185 if (!(data->has_fan & (1 << i)))
1186 continue;
1187 if (data->fan_div[i] == 0) {
1188 data->fan_div[i] = 7;
1189 nct6775_write_fan_div_common(data, i);
1190 }
1191 }
1192}
1193
1194static void nct6775_init_fan_common(struct device *dev,
1195 struct nct6775_data *data)
1196{
1197 int i;
1198 u8 reg;
1199
1200 if (data->has_fan_div)
1201 nct6775_init_fan_div(data);
1202
1203 /*
1204 * If fan_min is not set (0), set it to 0xff to disable it. This
1205 * prevents the unnecessary warning when fanX_min is reported as 0.
1206 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001207 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001208 if (data->has_fan_min & (1 << i)) {
1209 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1210 if (!reg)
1211 nct6775_write_value(data, data->REG_FAN_MIN[i],
1212 data->has_fan_div ? 0xff
1213 : 0xff1f);
1214 }
1215 }
1216}
1217
1218static void nct6775_select_fan_div(struct device *dev,
1219 struct nct6775_data *data, int nr, u16 reg)
1220{
1221 u8 fan_div = data->fan_div[nr];
1222 u16 fan_min;
1223
1224 if (!data->has_fan_div)
1225 return;
1226
1227 /*
1228 * If we failed to measure the fan speed, or the reported value is not
1229 * in the optimal range, and the clock divider can be modified,
1230 * let's try that for next time.
1231 */
1232 if (reg == 0x00 && fan_div < 0x07)
1233 fan_div++;
1234 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1235 fan_div--;
1236
1237 if (fan_div != data->fan_div[nr]) {
1238 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1239 nr + 1, div_from_reg(data->fan_div[nr]),
1240 div_from_reg(fan_div));
1241
1242 /* Preserve min limit if possible */
1243 if (data->has_fan_min & (1 << nr)) {
1244 fan_min = data->fan_min[nr];
1245 if (fan_div > data->fan_div[nr]) {
1246 if (fan_min != 255 && fan_min > 1)
1247 fan_min >>= 1;
1248 } else {
1249 if (fan_min != 255) {
1250 fan_min <<= 1;
1251 if (fan_min > 254)
1252 fan_min = 254;
1253 }
1254 }
1255 if (fan_min != data->fan_min[nr]) {
1256 data->fan_min[nr] = fan_min;
1257 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1258 fan_min);
1259 }
1260 }
1261 data->fan_div[nr] = fan_div;
1262 nct6775_write_fan_div_common(data, nr);
1263 }
1264}
1265
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001266static void nct6775_update_pwm(struct device *dev)
1267{
1268 struct nct6775_data *data = dev_get_drvdata(dev);
1269 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001270 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001271 bool duty_is_dc;
1272
1273 for (i = 0; i < data->pwm_num; i++) {
1274 if (!(data->has_pwm & (1 << i)))
1275 continue;
1276
1277 duty_is_dc = data->REG_PWM_MODE[i] &&
1278 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1279 & data->PWM_MODE_MASK[i]);
1280 data->pwm_mode[i] = duty_is_dc;
1281
1282 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1283 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1284 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1285 data->pwm[j][i]
1286 = nct6775_read_value(data,
1287 data->REG_PWM[j][i]);
1288 }
1289 }
1290
1291 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1292 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001293
1294 if (!data->temp_tolerance[0][i] ||
1295 data->pwm_enable[i] != speed_cruise)
1296 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1297 if (!data->target_speed_tolerance[i] ||
1298 data->pwm_enable[i] == speed_cruise) {
1299 u8 t = fanmodecfg & 0x0f;
1300 if (data->REG_TOLERANCE_H) {
1301 t |= (nct6775_read_value(data,
1302 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1303 }
1304 data->target_speed_tolerance[i] = t;
1305 }
1306
1307 data->temp_tolerance[1][i] =
1308 nct6775_read_value(data,
1309 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1310
1311 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1312 data->pwm_temp_sel[i] = reg & 0x1f;
1313 /* If fan can stop, report floor as 0 */
1314 if (reg & 0x80)
1315 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001316
1317 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1318 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1319 /* If weight is disabled, report weight source as 0 */
1320 if (j == 1 && !(reg & 0x80))
1321 data->pwm_weight_temp_sel[i] = 0;
1322
1323 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001324 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001325 data->weight_temp[j][i]
1326 = nct6775_read_value(data,
1327 data->REG_WEIGHT_TEMP[j][i]);
1328 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001329 }
1330}
1331
1332static void nct6775_update_pwm_limits(struct device *dev)
1333{
1334 struct nct6775_data *data = dev_get_drvdata(dev);
1335 int i, j;
1336 u8 reg;
1337 u16 reg_t;
1338
1339 for (i = 0; i < data->pwm_num; i++) {
1340 if (!(data->has_pwm & (1 << i)))
1341 continue;
1342
Guenter Roeckc409fd42013-04-09 05:04:00 -07001343 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001344 data->fan_time[j][i] =
1345 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1346 }
1347
1348 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1349 /* Update only in matching mode or if never updated */
1350 if (!data->target_temp[i] ||
1351 data->pwm_enable[i] == thermal_cruise)
1352 data->target_temp[i] = reg_t & data->target_temp_mask;
1353 if (!data->target_speed[i] ||
1354 data->pwm_enable[i] == speed_cruise) {
1355 if (data->REG_TOLERANCE_H) {
1356 reg_t |= (nct6775_read_value(data,
1357 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1358 }
1359 data->target_speed[i] = reg_t;
1360 }
1361
1362 for (j = 0; j < data->auto_pwm_num; j++) {
1363 data->auto_pwm[i][j] =
1364 nct6775_read_value(data,
1365 NCT6775_AUTO_PWM(data, i, j));
1366 data->auto_temp[i][j] =
1367 nct6775_read_value(data,
1368 NCT6775_AUTO_TEMP(data, i, j));
1369 }
1370
1371 /* critical auto_pwm temperature data */
1372 data->auto_temp[i][data->auto_pwm_num] =
1373 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1374
1375 switch (data->kind) {
1376 case nct6775:
1377 reg = nct6775_read_value(data,
1378 NCT6775_REG_CRITICAL_ENAB[i]);
1379 data->auto_pwm[i][data->auto_pwm_num] =
1380 (reg & 0x02) ? 0xff : 0x00;
1381 break;
1382 case nct6776:
1383 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1384 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001385 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001386 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001387 case nct6791:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001388 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001389 data->REG_CRITICAL_PWM_ENABLE[i]);
1390 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1391 reg = nct6775_read_value(data,
1392 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001393 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001394 reg = 0xff;
1395 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001396 break;
1397 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001398 }
1399}
1400
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001401static struct nct6775_data *nct6775_update_device(struct device *dev)
1402{
1403 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001404 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001405
1406 mutex_lock(&data->update_lock);
1407
Guenter Roeck6445e662013-04-21 09:13:28 -07001408 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001409 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001410 /* Fan clock dividers */
1411 nct6775_update_fan_div_common(data);
1412
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001413 /* Measured voltages and limits */
1414 for (i = 0; i < data->in_num; i++) {
1415 if (!(data->have_in & (1 << i)))
1416 continue;
1417
1418 data->in[i][0] = nct6775_read_value(data,
1419 data->REG_VIN[i]);
1420 data->in[i][1] = nct6775_read_value(data,
1421 data->REG_IN_MINMAX[0][i]);
1422 data->in[i][2] = nct6775_read_value(data,
1423 data->REG_IN_MINMAX[1][i]);
1424 }
1425
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001426 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001427 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001428 u16 reg;
1429
1430 if (!(data->has_fan & (1 << i)))
1431 continue;
1432
1433 reg = nct6775_read_value(data, data->REG_FAN[i]);
1434 data->rpm[i] = data->fan_from_reg(reg,
1435 data->fan_div[i]);
1436
1437 if (data->has_fan_min & (1 << i))
1438 data->fan_min[i] = nct6775_read_value(data,
1439 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001440 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001441 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1442 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001443
1444 nct6775_select_fan_div(dev, data, i, reg);
1445 }
1446
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001447 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001448 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001449
Guenter Roeckaa136e52012-12-04 03:26:05 -08001450 /* Measured temperatures and limits */
1451 for (i = 0; i < NUM_TEMP; i++) {
1452 if (!(data->have_temp & (1 << i)))
1453 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001454 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001455 if (data->reg_temp[j][i])
1456 data->temp[j][i]
1457 = nct6775_read_temp(data,
1458 data->reg_temp[j][i]);
1459 }
1460 if (!(data->have_temp_fixed & (1 << i)))
1461 continue;
1462 data->temp_offset[i]
1463 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1464 }
1465
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001466 data->alarms = 0;
1467 for (i = 0; i < NUM_REG_ALARM; i++) {
1468 u8 alarm;
1469 if (!data->REG_ALARM[i])
1470 continue;
1471 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1472 data->alarms |= ((u64)alarm) << (i << 3);
1473 }
1474
Guenter Roeck30846992013-06-24 22:21:59 -07001475 data->beeps = 0;
1476 for (i = 0; i < NUM_REG_BEEP; i++) {
1477 u8 beep;
1478 if (!data->REG_BEEP[i])
1479 continue;
1480 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1481 data->beeps |= ((u64)beep) << (i << 3);
1482 }
1483
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001484 data->last_updated = jiffies;
1485 data->valid = true;
1486 }
1487
1488 mutex_unlock(&data->update_lock);
1489 return data;
1490}
1491
1492/*
1493 * Sysfs callback functions
1494 */
1495static ssize_t
1496show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1497{
1498 struct nct6775_data *data = nct6775_update_device(dev);
1499 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1500 int nr = sattr->nr;
1501 int index = sattr->index;
1502 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1503}
1504
1505static ssize_t
1506store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1507 size_t count)
1508{
1509 struct nct6775_data *data = dev_get_drvdata(dev);
1510 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1511 int nr = sattr->nr;
1512 int index = sattr->index;
1513 unsigned long val;
1514 int err = kstrtoul(buf, 10, &val);
1515 if (err < 0)
1516 return err;
1517 mutex_lock(&data->update_lock);
1518 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001519 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001520 data->in[nr][index]);
1521 mutex_unlock(&data->update_lock);
1522 return count;
1523}
1524
1525static ssize_t
1526show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1527{
1528 struct nct6775_data *data = nct6775_update_device(dev);
1529 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1530 int nr = data->ALARM_BITS[sattr->index];
1531 return sprintf(buf, "%u\n",
1532 (unsigned int)((data->alarms >> nr) & 0x01));
1533}
1534
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001535static int find_temp_source(struct nct6775_data *data, int index, int count)
1536{
1537 int source = data->temp_src[index];
1538 int nr;
1539
1540 for (nr = 0; nr < count; nr++) {
1541 int src;
1542
1543 src = nct6775_read_value(data,
1544 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1545 if (src == source)
1546 return nr;
1547 }
1548 return -1;
1549}
1550
1551static ssize_t
1552show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1553{
1554 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1555 struct nct6775_data *data = nct6775_update_device(dev);
1556 unsigned int alarm = 0;
1557 int nr;
1558
1559 /*
1560 * For temperatures, there is no fixed mapping from registers to alarm
1561 * bits. Alarm bits are determined by the temperature source mapping.
1562 */
1563 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1564 if (nr >= 0) {
1565 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1566 alarm = (data->alarms >> bit) & 0x01;
1567 }
1568 return sprintf(buf, "%u\n", alarm);
1569}
1570
Guenter Roeck30846992013-06-24 22:21:59 -07001571static ssize_t
1572show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1573{
1574 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1575 struct nct6775_data *data = nct6775_update_device(dev);
1576 int nr = data->BEEP_BITS[sattr->index];
1577
1578 return sprintf(buf, "%u\n",
1579 (unsigned int)((data->beeps >> nr) & 0x01));
1580}
1581
1582static ssize_t
1583store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1584 size_t count)
1585{
1586 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1587 struct nct6775_data *data = dev_get_drvdata(dev);
1588 int nr = data->BEEP_BITS[sattr->index];
1589 int regindex = nr >> 3;
1590 unsigned long val;
1591
1592 int err = kstrtoul(buf, 10, &val);
1593 if (err < 0)
1594 return err;
1595 if (val > 1)
1596 return -EINVAL;
1597
1598 mutex_lock(&data->update_lock);
1599 if (val)
1600 data->beeps |= (1ULL << nr);
1601 else
1602 data->beeps &= ~(1ULL << nr);
1603 nct6775_write_value(data, data->REG_BEEP[regindex],
1604 (data->beeps >> (regindex << 3)) & 0xff);
1605 mutex_unlock(&data->update_lock);
1606 return count;
1607}
1608
1609static ssize_t
1610show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1611{
1612 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1613 struct nct6775_data *data = nct6775_update_device(dev);
1614 unsigned int beep = 0;
1615 int nr;
1616
1617 /*
1618 * For temperatures, there is no fixed mapping from registers to beep
1619 * enable bits. Beep enable bits are determined by the temperature
1620 * source mapping.
1621 */
1622 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1623 if (nr >= 0) {
1624 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1625 beep = (data->beeps >> bit) & 0x01;
1626 }
1627 return sprintf(buf, "%u\n", beep);
1628}
1629
1630static ssize_t
1631store_temp_beep(struct device *dev, struct device_attribute *attr,
1632 const char *buf, size_t count)
1633{
1634 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1635 struct nct6775_data *data = dev_get_drvdata(dev);
1636 int nr, bit, regindex;
1637 unsigned long val;
1638
1639 int err = kstrtoul(buf, 10, &val);
1640 if (err < 0)
1641 return err;
1642 if (val > 1)
1643 return -EINVAL;
1644
1645 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1646 if (nr < 0)
1647 return -ENODEV;
1648
1649 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1650 regindex = bit >> 3;
1651
1652 mutex_lock(&data->update_lock);
1653 if (val)
1654 data->beeps |= (1ULL << bit);
1655 else
1656 data->beeps &= ~(1ULL << bit);
1657 nct6775_write_value(data, data->REG_BEEP[regindex],
1658 (data->beeps >> (regindex << 3)) & 0xff);
1659 mutex_unlock(&data->update_lock);
1660
1661 return count;
1662}
1663
Guenter Roeckf73cf632013-03-18 09:22:50 -07001664static umode_t nct6775_in_is_visible(struct kobject *kobj,
1665 struct attribute *attr, int index)
1666{
1667 struct device *dev = container_of(kobj, struct device, kobj);
1668 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001669 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001670
Guenter Roeckf73cf632013-03-18 09:22:50 -07001671 if (!(data->have_in & (1 << in)))
1672 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001673
Guenter Roeckf73cf632013-03-18 09:22:50 -07001674 return attr->mode;
1675}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001676
Guenter Roeckf73cf632013-03-18 09:22:50 -07001677SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1678SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001679SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1680 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001681SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1682 store_in_reg, 0, 1);
1683SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1684 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001685
Guenter Roeckf73cf632013-03-18 09:22:50 -07001686/*
1687 * nct6775_in_is_visible uses the index into the following array
1688 * to determine if attributes should be created or not.
1689 * Any change in order or content must be matched.
1690 */
1691static struct sensor_device_template *nct6775_attributes_in_template[] = {
1692 &sensor_dev_template_in_input,
1693 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001694 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001695 &sensor_dev_template_in_min,
1696 &sensor_dev_template_in_max,
1697 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001698};
1699
Guenter Roeckf73cf632013-03-18 09:22:50 -07001700static struct sensor_template_group nct6775_in_template_group = {
1701 .templates = nct6775_attributes_in_template,
1702 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001703};
1704
1705static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001706show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1707{
1708 struct nct6775_data *data = nct6775_update_device(dev);
1709 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1710 int nr = sattr->index;
1711 return sprintf(buf, "%d\n", data->rpm[nr]);
1712}
1713
1714static ssize_t
1715show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1716{
1717 struct nct6775_data *data = nct6775_update_device(dev);
1718 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1719 int nr = sattr->index;
1720 return sprintf(buf, "%d\n",
1721 data->fan_from_reg_min(data->fan_min[nr],
1722 data->fan_div[nr]));
1723}
1724
1725static ssize_t
1726show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1727{
1728 struct nct6775_data *data = nct6775_update_device(dev);
1729 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1730 int nr = sattr->index;
1731 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1732}
1733
1734static ssize_t
1735store_fan_min(struct device *dev, struct device_attribute *attr,
1736 const char *buf, size_t count)
1737{
1738 struct nct6775_data *data = dev_get_drvdata(dev);
1739 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1740 int nr = sattr->index;
1741 unsigned long val;
1742 int err;
1743 unsigned int reg;
1744 u8 new_div;
1745
1746 err = kstrtoul(buf, 10, &val);
1747 if (err < 0)
1748 return err;
1749
1750 mutex_lock(&data->update_lock);
1751 if (!data->has_fan_div) {
1752 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1753 if (!val) {
1754 val = 0xff1f;
1755 } else {
1756 if (val > 1350000U)
1757 val = 135000U;
1758 val = 1350000U / val;
1759 val = (val & 0x1f) | ((val << 3) & 0xff00);
1760 }
1761 data->fan_min[nr] = val;
1762 goto write_min; /* Leave fan divider alone */
1763 }
1764 if (!val) {
1765 /* No min limit, alarm disabled */
1766 data->fan_min[nr] = 255;
1767 new_div = data->fan_div[nr]; /* No change */
1768 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1769 goto write_div;
1770 }
1771 reg = 1350000U / val;
1772 if (reg >= 128 * 255) {
1773 /*
1774 * Speed below this value cannot possibly be represented,
1775 * even with the highest divider (128)
1776 */
1777 data->fan_min[nr] = 254;
1778 new_div = 7; /* 128 == (1 << 7) */
1779 dev_warn(dev,
1780 "fan%u low limit %lu below minimum %u, set to minimum\n",
1781 nr + 1, val, data->fan_from_reg_min(254, 7));
1782 } else if (!reg) {
1783 /*
1784 * Speed above this value cannot possibly be represented,
1785 * even with the lowest divider (1)
1786 */
1787 data->fan_min[nr] = 1;
1788 new_div = 0; /* 1 == (1 << 0) */
1789 dev_warn(dev,
1790 "fan%u low limit %lu above maximum %u, set to maximum\n",
1791 nr + 1, val, data->fan_from_reg_min(1, 0));
1792 } else {
1793 /*
1794 * Automatically pick the best divider, i.e. the one such
1795 * that the min limit will correspond to a register value
1796 * in the 96..192 range
1797 */
1798 new_div = 0;
1799 while (reg > 192 && new_div < 7) {
1800 reg >>= 1;
1801 new_div++;
1802 }
1803 data->fan_min[nr] = reg;
1804 }
1805
1806write_div:
1807 /*
1808 * Write both the fan clock divider (if it changed) and the new
1809 * fan min (unconditionally)
1810 */
1811 if (new_div != data->fan_div[nr]) {
1812 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1813 nr + 1, div_from_reg(data->fan_div[nr]),
1814 div_from_reg(new_div));
1815 data->fan_div[nr] = new_div;
1816 nct6775_write_fan_div_common(data, nr);
1817 /* Give the chip time to sample a new speed value */
1818 data->last_updated = jiffies;
1819 }
1820
1821write_min:
1822 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1823 mutex_unlock(&data->update_lock);
1824
1825 return count;
1826}
1827
Guenter Roeck5c25d952012-12-11 07:29:06 -08001828static ssize_t
1829show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1830{
1831 struct nct6775_data *data = nct6775_update_device(dev);
1832 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1833 int p = data->fan_pulses[sattr->index];
1834
1835 return sprintf(buf, "%d\n", p ? : 4);
1836}
1837
1838static ssize_t
1839store_fan_pulses(struct device *dev, struct device_attribute *attr,
1840 const char *buf, size_t count)
1841{
1842 struct nct6775_data *data = dev_get_drvdata(dev);
1843 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1844 int nr = sattr->index;
1845 unsigned long val;
1846 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001847 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001848
1849 err = kstrtoul(buf, 10, &val);
1850 if (err < 0)
1851 return err;
1852
1853 if (val > 4)
1854 return -EINVAL;
1855
1856 mutex_lock(&data->update_lock);
1857 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001858 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1859 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1860 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1861 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001862 mutex_unlock(&data->update_lock);
1863
1864 return count;
1865}
1866
Guenter Roeckf73cf632013-03-18 09:22:50 -07001867static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1868 struct attribute *attr, int index)
1869{
1870 struct device *dev = container_of(kobj, struct device, kobj);
1871 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001872 int fan = index / 6; /* fan index */
1873 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001874
1875 if (!(data->has_fan & (1 << fan)))
1876 return 0;
1877
1878 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1879 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001880 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001881 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001882 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1883 return 0;
1884 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001885 return 0;
1886
1887 return attr->mode;
1888}
1889
1890SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1891SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1892 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001893SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1894 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001895SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1896 store_fan_pulses, 0);
1897SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1898 store_fan_min, 0);
1899SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1900
1901/*
1902 * nct6775_fan_is_visible uses the index into the following array
1903 * to determine if attributes should be created or not.
1904 * Any change in order or content must be matched.
1905 */
1906static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1907 &sensor_dev_template_fan_input,
1908 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001909 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001910 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001911 &sensor_dev_template_fan_min, /* 4 */
1912 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001913 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001914};
1915
Guenter Roeckf73cf632013-03-18 09:22:50 -07001916static struct sensor_template_group nct6775_fan_template_group = {
1917 .templates = nct6775_attributes_fan_template,
1918 .is_visible = nct6775_fan_is_visible,
1919 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001920};
1921
1922static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001923show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1924{
1925 struct nct6775_data *data = nct6775_update_device(dev);
1926 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1927 int nr = sattr->index;
1928 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1929}
1930
1931static ssize_t
1932show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1933{
1934 struct nct6775_data *data = nct6775_update_device(dev);
1935 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1936 int nr = sattr->nr;
1937 int index = sattr->index;
1938
1939 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1940}
1941
1942static ssize_t
1943store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1944 size_t count)
1945{
1946 struct nct6775_data *data = dev_get_drvdata(dev);
1947 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1948 int nr = sattr->nr;
1949 int index = sattr->index;
1950 int err;
1951 long val;
1952
1953 err = kstrtol(buf, 10, &val);
1954 if (err < 0)
1955 return err;
1956
1957 mutex_lock(&data->update_lock);
1958 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1959 nct6775_write_temp(data, data->reg_temp[index][nr],
1960 data->temp[index][nr]);
1961 mutex_unlock(&data->update_lock);
1962 return count;
1963}
1964
1965static ssize_t
1966show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1967{
1968 struct nct6775_data *data = nct6775_update_device(dev);
1969 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1970
1971 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1972}
1973
1974static ssize_t
1975store_temp_offset(struct device *dev, struct device_attribute *attr,
1976 const char *buf, size_t count)
1977{
1978 struct nct6775_data *data = dev_get_drvdata(dev);
1979 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1980 int nr = sattr->index;
1981 long val;
1982 int err;
1983
1984 err = kstrtol(buf, 10, &val);
1985 if (err < 0)
1986 return err;
1987
1988 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1989
1990 mutex_lock(&data->update_lock);
1991 data->temp_offset[nr] = val;
1992 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1993 mutex_unlock(&data->update_lock);
1994
1995 return count;
1996}
1997
1998static ssize_t
1999show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
2000{
2001 struct nct6775_data *data = nct6775_update_device(dev);
2002 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2003 int nr = sattr->index;
2004 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2005}
2006
2007static ssize_t
2008store_temp_type(struct device *dev, struct device_attribute *attr,
2009 const char *buf, size_t count)
2010{
2011 struct nct6775_data *data = nct6775_update_device(dev);
2012 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2013 int nr = sattr->index;
2014 unsigned long val;
2015 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002016 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002017
2018 err = kstrtoul(buf, 10, &val);
2019 if (err < 0)
2020 return err;
2021
2022 if (val != 1 && val != 3 && val != 4)
2023 return -EINVAL;
2024
2025 mutex_lock(&data->update_lock);
2026
2027 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002028 vbit = 0x02 << nr;
2029 dbit = data->DIODE_MASK << nr;
2030 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2031 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002032 switch (val) {
2033 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002034 vbat |= vbit;
2035 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002036 break;
2037 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002038 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002039 break;
2040 case 4: /* thermistor */
2041 break;
2042 }
2043 nct6775_write_value(data, data->REG_VBAT, vbat);
2044 nct6775_write_value(data, data->REG_DIODE, diode);
2045
2046 mutex_unlock(&data->update_lock);
2047 return count;
2048}
2049
Guenter Roeckf73cf632013-03-18 09:22:50 -07002050static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2051 struct attribute *attr, int index)
2052{
2053 struct device *dev = container_of(kobj, struct device, kobj);
2054 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002055 int temp = index / 10; /* temp index */
2056 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002057
2058 if (!(data->have_temp & (1 << temp)))
2059 return 0;
2060
2061 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2062 return 0; /* alarm */
2063
Guenter Roeck30846992013-06-24 22:21:59 -07002064 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2065 return 0; /* beep */
2066
2067 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002068 return 0;
2069
Guenter Roeck30846992013-06-24 22:21:59 -07002070 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002071 return 0;
2072
Guenter Roeck30846992013-06-24 22:21:59 -07002073 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002074 return 0;
2075
Guenter Roeck30846992013-06-24 22:21:59 -07002076 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002077 return 0;
2078
2079 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002080 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002081 return 0;
2082
2083 return attr->mode;
2084}
2085
2086SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2087SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2088SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2089 store_temp, 0, 1);
2090SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2091 show_temp, store_temp, 0, 2);
2092SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2093 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002094SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2095 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002096SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2097 show_temp_offset, store_temp_offset, 0);
2098SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2099 store_temp_type, 0);
2100SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002101SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2102 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002103
2104/*
2105 * nct6775_temp_is_visible uses the index into the following array
2106 * to determine if attributes should be created or not.
2107 * Any change in order or content must be matched.
2108 */
2109static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2110 &sensor_dev_template_temp_input,
2111 &sensor_dev_template_temp_label,
2112 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002113 &sensor_dev_template_temp_beep, /* 3 */
2114 &sensor_dev_template_temp_max, /* 4 */
2115 &sensor_dev_template_temp_max_hyst, /* 5 */
2116 &sensor_dev_template_temp_crit, /* 6 */
2117 &sensor_dev_template_temp_lcrit, /* 7 */
2118 &sensor_dev_template_temp_offset, /* 8 */
2119 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002120 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002121};
2122
Guenter Roeckf73cf632013-03-18 09:22:50 -07002123static struct sensor_template_group nct6775_temp_template_group = {
2124 .templates = nct6775_attributes_temp_template,
2125 .is_visible = nct6775_temp_is_visible,
2126 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002127};
2128
Guenter Roeckaa136e52012-12-04 03:26:05 -08002129static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002130show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2131{
2132 struct nct6775_data *data = nct6775_update_device(dev);
2133 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2134
2135 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2136}
2137
2138static ssize_t
2139store_pwm_mode(struct device *dev, struct device_attribute *attr,
2140 const char *buf, size_t count)
2141{
2142 struct nct6775_data *data = dev_get_drvdata(dev);
2143 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2144 int nr = sattr->index;
2145 unsigned long val;
2146 int err;
2147 u8 reg;
2148
2149 err = kstrtoul(buf, 10, &val);
2150 if (err < 0)
2151 return err;
2152
2153 if (val > 1)
2154 return -EINVAL;
2155
2156 /* Setting DC mode is not supported for all chips/channels */
2157 if (data->REG_PWM_MODE[nr] == 0) {
2158 if (val)
2159 return -EINVAL;
2160 return count;
2161 }
2162
2163 mutex_lock(&data->update_lock);
2164 data->pwm_mode[nr] = val;
2165 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2166 reg &= ~data->PWM_MODE_MASK[nr];
2167 if (val)
2168 reg |= data->PWM_MODE_MASK[nr];
2169 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2170 mutex_unlock(&data->update_lock);
2171 return count;
2172}
2173
2174static ssize_t
2175show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2176{
2177 struct nct6775_data *data = nct6775_update_device(dev);
2178 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2179 int nr = sattr->nr;
2180 int index = sattr->index;
2181 int pwm;
2182
2183 /*
2184 * For automatic fan control modes, show current pwm readings.
2185 * Otherwise, show the configured value.
2186 */
2187 if (index == 0 && data->pwm_enable[nr] > manual)
2188 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2189 else
2190 pwm = data->pwm[index][nr];
2191
2192 return sprintf(buf, "%d\n", pwm);
2193}
2194
2195static ssize_t
2196store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2197 size_t count)
2198{
2199 struct nct6775_data *data = dev_get_drvdata(dev);
2200 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2201 int nr = sattr->nr;
2202 int index = sattr->index;
2203 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002204 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2205 int maxval[7]
2206 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002207 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002208 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002209
2210 err = kstrtoul(buf, 10, &val);
2211 if (err < 0)
2212 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002213 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002214
2215 mutex_lock(&data->update_lock);
2216 data->pwm[index][nr] = val;
2217 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002218 if (index == 2) { /* floor: disable if val == 0 */
2219 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2220 reg &= 0x7f;
2221 if (val)
2222 reg |= 0x80;
2223 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2224 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002225 mutex_unlock(&data->update_lock);
2226 return count;
2227}
2228
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002229/* Returns 0 if OK, -EINVAL otherwise */
2230static int check_trip_points(struct nct6775_data *data, int nr)
2231{
2232 int i;
2233
2234 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2235 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2236 return -EINVAL;
2237 }
2238 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2239 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2240 return -EINVAL;
2241 }
2242 /* validate critical temperature and pwm if enabled (pwm > 0) */
2243 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2244 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2245 data->auto_temp[nr][data->auto_pwm_num] ||
2246 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2247 data->auto_pwm[nr][data->auto_pwm_num])
2248 return -EINVAL;
2249 }
2250 return 0;
2251}
2252
2253static void pwm_update_registers(struct nct6775_data *data, int nr)
2254{
2255 u8 reg;
2256
2257 switch (data->pwm_enable[nr]) {
2258 case off:
2259 case manual:
2260 break;
2261 case speed_cruise:
2262 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2263 reg = (reg & ~data->tolerance_mask) |
2264 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2265 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2266 nct6775_write_value(data, data->REG_TARGET[nr],
2267 data->target_speed[nr] & 0xff);
2268 if (data->REG_TOLERANCE_H) {
2269 reg = (data->target_speed[nr] >> 8) & 0x0f;
2270 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2271 nct6775_write_value(data,
2272 data->REG_TOLERANCE_H[nr],
2273 reg);
2274 }
2275 break;
2276 case thermal_cruise:
2277 nct6775_write_value(data, data->REG_TARGET[nr],
2278 data->target_temp[nr]);
2279 /* intentional */
2280 default:
2281 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2282 reg = (reg & ~data->tolerance_mask) |
2283 data->temp_tolerance[0][nr];
2284 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2285 break;
2286 }
2287}
2288
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002289static ssize_t
2290show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2291{
2292 struct nct6775_data *data = nct6775_update_device(dev);
2293 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2294
2295 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2296}
2297
2298static ssize_t
2299store_pwm_enable(struct device *dev, struct device_attribute *attr,
2300 const char *buf, size_t count)
2301{
2302 struct nct6775_data *data = dev_get_drvdata(dev);
2303 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2304 int nr = sattr->index;
2305 unsigned long val;
2306 int err;
2307 u16 reg;
2308
2309 err = kstrtoul(buf, 10, &val);
2310 if (err < 0)
2311 return err;
2312
2313 if (val > sf4)
2314 return -EINVAL;
2315
2316 if (val == sf3 && data->kind != nct6775)
2317 return -EINVAL;
2318
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002319 if (val == sf4 && check_trip_points(data, nr)) {
2320 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2321 dev_err(dev, "Adjust trip points and try again\n");
2322 return -EINVAL;
2323 }
2324
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002325 mutex_lock(&data->update_lock);
2326 data->pwm_enable[nr] = val;
2327 if (val == off) {
2328 /*
2329 * turn off pwm control: select manual mode, set pwm to maximum
2330 */
2331 data->pwm[0][nr] = 255;
2332 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2333 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002334 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002335 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2336 reg &= 0x0f;
2337 reg |= pwm_enable_to_reg(val) << 4;
2338 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2339 mutex_unlock(&data->update_lock);
2340 return count;
2341}
2342
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002343static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002344show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002345{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002346 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002347
2348 for (i = 0; i < NUM_TEMP; i++) {
2349 if (!(data->have_temp & (1 << i)))
2350 continue;
2351 if (src == data->temp_src[i]) {
2352 sel = i + 1;
2353 break;
2354 }
2355 }
2356
2357 return sprintf(buf, "%d\n", sel);
2358}
2359
2360static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002361show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2362{
2363 struct nct6775_data *data = nct6775_update_device(dev);
2364 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2365 int index = sattr->index;
2366
2367 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2368}
2369
2370static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002371store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2372 const char *buf, size_t count)
2373{
2374 struct nct6775_data *data = nct6775_update_device(dev);
2375 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2376 int nr = sattr->index;
2377 unsigned long val;
2378 int err, reg, src;
2379
2380 err = kstrtoul(buf, 10, &val);
2381 if (err < 0)
2382 return err;
2383 if (val == 0 || val > NUM_TEMP)
2384 return -EINVAL;
2385 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2386 return -EINVAL;
2387
2388 mutex_lock(&data->update_lock);
2389 src = data->temp_src[val - 1];
2390 data->pwm_temp_sel[nr] = src;
2391 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2392 reg &= 0xe0;
2393 reg |= src;
2394 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2395 mutex_unlock(&data->update_lock);
2396
2397 return count;
2398}
2399
2400static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002401show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2402 char *buf)
2403{
2404 struct nct6775_data *data = nct6775_update_device(dev);
2405 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2406 int index = sattr->index;
2407
2408 return show_pwm_temp_sel_common(data, buf,
2409 data->pwm_weight_temp_sel[index]);
2410}
2411
2412static ssize_t
2413store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2414 const char *buf, size_t count)
2415{
2416 struct nct6775_data *data = nct6775_update_device(dev);
2417 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2418 int nr = sattr->index;
2419 unsigned long val;
2420 int err, reg, src;
2421
2422 err = kstrtoul(buf, 10, &val);
2423 if (err < 0)
2424 return err;
2425 if (val > NUM_TEMP)
2426 return -EINVAL;
2427 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2428 !data->temp_src[val - 1]))
2429 return -EINVAL;
2430
2431 mutex_lock(&data->update_lock);
2432 if (val) {
2433 src = data->temp_src[val - 1];
2434 data->pwm_weight_temp_sel[nr] = src;
2435 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2436 reg &= 0xe0;
2437 reg |= (src | 0x80);
2438 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2439 } else {
2440 data->pwm_weight_temp_sel[nr] = 0;
2441 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2442 reg &= 0x7f;
2443 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2444 }
2445 mutex_unlock(&data->update_lock);
2446
2447 return count;
2448}
2449
2450static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002451show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2452{
2453 struct nct6775_data *data = nct6775_update_device(dev);
2454 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2455
2456 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2457}
2458
2459static ssize_t
2460store_target_temp(struct device *dev, struct device_attribute *attr,
2461 const char *buf, size_t count)
2462{
2463 struct nct6775_data *data = dev_get_drvdata(dev);
2464 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2465 int nr = sattr->index;
2466 unsigned long val;
2467 int err;
2468
2469 err = kstrtoul(buf, 10, &val);
2470 if (err < 0)
2471 return err;
2472
2473 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2474 data->target_temp_mask);
2475
2476 mutex_lock(&data->update_lock);
2477 data->target_temp[nr] = val;
2478 pwm_update_registers(data, nr);
2479 mutex_unlock(&data->update_lock);
2480 return count;
2481}
2482
2483static ssize_t
2484show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2485{
2486 struct nct6775_data *data = nct6775_update_device(dev);
2487 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2488 int nr = sattr->index;
2489
2490 return sprintf(buf, "%d\n",
2491 fan_from_reg16(data->target_speed[nr],
2492 data->fan_div[nr]));
2493}
2494
2495static ssize_t
2496store_target_speed(struct device *dev, struct device_attribute *attr,
2497 const char *buf, size_t count)
2498{
2499 struct nct6775_data *data = dev_get_drvdata(dev);
2500 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2501 int nr = sattr->index;
2502 unsigned long val;
2503 int err;
2504 u16 speed;
2505
2506 err = kstrtoul(buf, 10, &val);
2507 if (err < 0)
2508 return err;
2509
2510 val = clamp_val(val, 0, 1350000U);
2511 speed = fan_to_reg(val, data->fan_div[nr]);
2512
2513 mutex_lock(&data->update_lock);
2514 data->target_speed[nr] = speed;
2515 pwm_update_registers(data, nr);
2516 mutex_unlock(&data->update_lock);
2517 return count;
2518}
2519
2520static ssize_t
2521show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2522 char *buf)
2523{
2524 struct nct6775_data *data = nct6775_update_device(dev);
2525 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2526 int nr = sattr->nr;
2527 int index = sattr->index;
2528
2529 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2530}
2531
2532static ssize_t
2533store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2534 const char *buf, size_t count)
2535{
2536 struct nct6775_data *data = dev_get_drvdata(dev);
2537 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2538 int nr = sattr->nr;
2539 int index = sattr->index;
2540 unsigned long val;
2541 int err;
2542
2543 err = kstrtoul(buf, 10, &val);
2544 if (err < 0)
2545 return err;
2546
2547 /* Limit tolerance as needed */
2548 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2549
2550 mutex_lock(&data->update_lock);
2551 data->temp_tolerance[index][nr] = val;
2552 if (index)
2553 pwm_update_registers(data, nr);
2554 else
2555 nct6775_write_value(data,
2556 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2557 val);
2558 mutex_unlock(&data->update_lock);
2559 return count;
2560}
2561
2562/*
2563 * Fan speed tolerance is a tricky beast, since the associated register is
2564 * a tick counter, but the value is reported and configured as rpm.
2565 * Compute resulting low and high rpm values and report the difference.
2566 */
2567static ssize_t
2568show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2569 char *buf)
2570{
2571 struct nct6775_data *data = nct6775_update_device(dev);
2572 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2573 int nr = sattr->index;
2574 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2575 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2576 int tolerance;
2577
2578 if (low <= 0)
2579 low = 1;
2580 if (high > 0xffff)
2581 high = 0xffff;
2582 if (high < low)
2583 high = low;
2584
2585 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2586 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2587
2588 return sprintf(buf, "%d\n", tolerance);
2589}
2590
2591static ssize_t
2592store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2593 const char *buf, size_t count)
2594{
2595 struct nct6775_data *data = dev_get_drvdata(dev);
2596 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2597 int nr = sattr->index;
2598 unsigned long val;
2599 int err;
2600 int low, high;
2601
2602 err = kstrtoul(buf, 10, &val);
2603 if (err < 0)
2604 return err;
2605
2606 high = fan_from_reg16(data->target_speed[nr],
2607 data->fan_div[nr]) + val;
2608 low = fan_from_reg16(data->target_speed[nr],
2609 data->fan_div[nr]) - val;
2610 if (low <= 0)
2611 low = 1;
2612 if (high < low)
2613 high = low;
2614
2615 val = (fan_to_reg(low, data->fan_div[nr]) -
2616 fan_to_reg(high, data->fan_div[nr])) / 2;
2617
2618 /* Limit tolerance as needed */
2619 val = clamp_val(val, 0, data->speed_tolerance_limit);
2620
2621 mutex_lock(&data->update_lock);
2622 data->target_speed_tolerance[nr] = val;
2623 pwm_update_registers(data, nr);
2624 mutex_unlock(&data->update_lock);
2625 return count;
2626}
2627
Guenter Roeckf73cf632013-03-18 09:22:50 -07002628SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2629SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2630 store_pwm_mode, 0);
2631SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2632 store_pwm_enable, 0);
2633SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2634 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2635SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2636 show_target_temp, store_target_temp, 0);
2637SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2638 show_target_speed, store_target_speed, 0);
2639SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2640 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002641
2642/* Smart Fan registers */
2643
2644static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002645show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2646{
2647 struct nct6775_data *data = nct6775_update_device(dev);
2648 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2649 int nr = sattr->nr;
2650 int index = sattr->index;
2651
2652 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2653}
2654
2655static ssize_t
2656store_weight_temp(struct device *dev, struct device_attribute *attr,
2657 const char *buf, size_t count)
2658{
2659 struct nct6775_data *data = dev_get_drvdata(dev);
2660 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2661 int nr = sattr->nr;
2662 int index = sattr->index;
2663 unsigned long val;
2664 int err;
2665
2666 err = kstrtoul(buf, 10, &val);
2667 if (err < 0)
2668 return err;
2669
2670 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2671
2672 mutex_lock(&data->update_lock);
2673 data->weight_temp[index][nr] = val;
2674 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2675 mutex_unlock(&data->update_lock);
2676 return count;
2677}
2678
Guenter Roeckf73cf632013-03-18 09:22:50 -07002679SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2680 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2681SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2682 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2683SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2684 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2685SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2686 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2687SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2688 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2689SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2690 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002691
2692static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002693show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2694{
2695 struct nct6775_data *data = nct6775_update_device(dev);
2696 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2697 int nr = sattr->nr;
2698 int index = sattr->index;
2699
2700 return sprintf(buf, "%d\n",
2701 step_time_from_reg(data->fan_time[index][nr],
2702 data->pwm_mode[nr]));
2703}
2704
2705static ssize_t
2706store_fan_time(struct device *dev, struct device_attribute *attr,
2707 const char *buf, size_t count)
2708{
2709 struct nct6775_data *data = dev_get_drvdata(dev);
2710 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2711 int nr = sattr->nr;
2712 int index = sattr->index;
2713 unsigned long val;
2714 int err;
2715
2716 err = kstrtoul(buf, 10, &val);
2717 if (err < 0)
2718 return err;
2719
2720 val = step_time_to_reg(val, data->pwm_mode[nr]);
2721 mutex_lock(&data->update_lock);
2722 data->fan_time[index][nr] = val;
2723 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2724 mutex_unlock(&data->update_lock);
2725 return count;
2726}
2727
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002728static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002729show_name(struct device *dev, struct device_attribute *attr, char *buf)
2730{
2731 struct nct6775_data *data = dev_get_drvdata(dev);
2732
2733 return sprintf(buf, "%s\n", data->name);
2734}
2735
2736static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2737
2738static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002739show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2740{
2741 struct nct6775_data *data = nct6775_update_device(dev);
2742 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2743
2744 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2745}
2746
2747static ssize_t
2748store_auto_pwm(struct device *dev, struct device_attribute *attr,
2749 const char *buf, size_t count)
2750{
2751 struct nct6775_data *data = dev_get_drvdata(dev);
2752 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2753 int nr = sattr->nr;
2754 int point = sattr->index;
2755 unsigned long val;
2756 int err;
2757 u8 reg;
2758
2759 err = kstrtoul(buf, 10, &val);
2760 if (err < 0)
2761 return err;
2762 if (val > 255)
2763 return -EINVAL;
2764
2765 if (point == data->auto_pwm_num) {
2766 if (data->kind != nct6775 && !val)
2767 return -EINVAL;
2768 if (data->kind != nct6779 && val)
2769 val = 0xff;
2770 }
2771
2772 mutex_lock(&data->update_lock);
2773 data->auto_pwm[nr][point] = val;
2774 if (point < data->auto_pwm_num) {
2775 nct6775_write_value(data,
2776 NCT6775_AUTO_PWM(data, nr, point),
2777 data->auto_pwm[nr][point]);
2778 } else {
2779 switch (data->kind) {
2780 case nct6775:
2781 /* disable if needed (pwm == 0) */
2782 reg = nct6775_read_value(data,
2783 NCT6775_REG_CRITICAL_ENAB[nr]);
2784 if (val)
2785 reg |= 0x02;
2786 else
2787 reg &= ~0x02;
2788 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2789 reg);
2790 break;
2791 case nct6776:
2792 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002793 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002794 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002795 case nct6791:
Guenter Roeck6c009502012-07-01 08:23:15 -07002796 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002797 val);
2798 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002799 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002800 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002801 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002802 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002803 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002804 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002805 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002806 reg);
2807 break;
2808 }
2809 }
2810 mutex_unlock(&data->update_lock);
2811 return count;
2812}
2813
2814static ssize_t
2815show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2816{
2817 struct nct6775_data *data = nct6775_update_device(dev);
2818 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2819 int nr = sattr->nr;
2820 int point = sattr->index;
2821
2822 /*
2823 * We don't know for sure if the temperature is signed or unsigned.
2824 * Assume it is unsigned.
2825 */
2826 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2827}
2828
2829static ssize_t
2830store_auto_temp(struct device *dev, struct device_attribute *attr,
2831 const char *buf, size_t count)
2832{
2833 struct nct6775_data *data = dev_get_drvdata(dev);
2834 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2835 int nr = sattr->nr;
2836 int point = sattr->index;
2837 unsigned long val;
2838 int err;
2839
2840 err = kstrtoul(buf, 10, &val);
2841 if (err)
2842 return err;
2843 if (val > 255000)
2844 return -EINVAL;
2845
2846 mutex_lock(&data->update_lock);
2847 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2848 if (point < data->auto_pwm_num) {
2849 nct6775_write_value(data,
2850 NCT6775_AUTO_TEMP(data, nr, point),
2851 data->auto_temp[nr][point]);
2852 } else {
2853 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2854 data->auto_temp[nr][point]);
2855 }
2856 mutex_unlock(&data->update_lock);
2857 return count;
2858}
2859
Guenter Roeckf73cf632013-03-18 09:22:50 -07002860static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2861 struct attribute *attr, int index)
2862{
2863 struct device *dev = container_of(kobj, struct device, kobj);
2864 struct nct6775_data *data = dev_get_drvdata(dev);
2865 int pwm = index / 36; /* pwm index */
2866 int nr = index % 36; /* attribute index */
2867
2868 if (!(data->has_pwm & (1 << pwm)))
2869 return 0;
2870
2871 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2872 return 0;
2873 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2874 return 0;
2875 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2876 return 0;
2877
2878 if (nr >= 22 && nr <= 35) { /* auto point */
2879 int api = (nr - 22) / 2; /* auto point index */
2880
2881 if (api > data->auto_pwm_num)
2882 return 0;
2883 }
2884 return attr->mode;
2885}
2886
2887SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2888 show_fan_time, store_fan_time, 0, 0);
2889SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2890 show_fan_time, store_fan_time, 0, 1);
2891SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2892 show_fan_time, store_fan_time, 0, 2);
2893SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2894 store_pwm, 0, 1);
2895SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2896 store_pwm, 0, 2);
2897SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2898 show_temp_tolerance, store_temp_tolerance, 0, 0);
2899SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2900 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2901 0, 1);
2902
2903SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2904 0, 3);
2905
2906SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2907 store_pwm, 0, 4);
2908
2909SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2910 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2911SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2912 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2913
2914SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2915 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2916SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2917 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2918
2919SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2920 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2921SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2922 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2923
2924SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2925 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2926SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2927 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2928
2929SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2930 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2931SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2932 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2933
2934SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2935 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2936SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2937 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2938
2939SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2940 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2941SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2942 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2943
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002944/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002945 * nct6775_pwm_is_visible uses the index into the following array
2946 * to determine if attributes should be created or not.
2947 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002948 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002949static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2950 &sensor_dev_template_pwm,
2951 &sensor_dev_template_pwm_mode,
2952 &sensor_dev_template_pwm_enable,
2953 &sensor_dev_template_pwm_temp_sel,
2954 &sensor_dev_template_pwm_temp_tolerance,
2955 &sensor_dev_template_pwm_crit_temp_tolerance,
2956 &sensor_dev_template_pwm_target_temp,
2957 &sensor_dev_template_fan_target,
2958 &sensor_dev_template_fan_tolerance,
2959 &sensor_dev_template_pwm_stop_time,
2960 &sensor_dev_template_pwm_step_up_time,
2961 &sensor_dev_template_pwm_step_down_time,
2962 &sensor_dev_template_pwm_start,
2963 &sensor_dev_template_pwm_floor,
2964 &sensor_dev_template_pwm_weight_temp_sel,
2965 &sensor_dev_template_pwm_weight_temp_step,
2966 &sensor_dev_template_pwm_weight_temp_step_tol,
2967 &sensor_dev_template_pwm_weight_temp_step_base,
2968 &sensor_dev_template_pwm_weight_duty_step,
2969 &sensor_dev_template_pwm_max, /* 19 */
2970 &sensor_dev_template_pwm_step, /* 20 */
2971 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2972 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2973 &sensor_dev_template_pwm_auto_point1_temp,
2974 &sensor_dev_template_pwm_auto_point2_pwm,
2975 &sensor_dev_template_pwm_auto_point2_temp,
2976 &sensor_dev_template_pwm_auto_point3_pwm,
2977 &sensor_dev_template_pwm_auto_point3_temp,
2978 &sensor_dev_template_pwm_auto_point4_pwm,
2979 &sensor_dev_template_pwm_auto_point4_temp,
2980 &sensor_dev_template_pwm_auto_point5_pwm,
2981 &sensor_dev_template_pwm_auto_point5_temp,
2982 &sensor_dev_template_pwm_auto_point6_pwm,
2983 &sensor_dev_template_pwm_auto_point6_temp,
2984 &sensor_dev_template_pwm_auto_point7_pwm,
2985 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002986
Guenter Roeckf73cf632013-03-18 09:22:50 -07002987 NULL
2988};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002989
Guenter Roeckf73cf632013-03-18 09:22:50 -07002990static struct sensor_template_group nct6775_pwm_template_group = {
2991 .templates = nct6775_attributes_pwm_template,
2992 .is_visible = nct6775_pwm_is_visible,
2993 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002994};
2995
2996static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002997show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2998{
2999 struct nct6775_data *data = dev_get_drvdata(dev);
3000 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3001}
3002
3003static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3004
Guenter Roecka6bd5872012-12-04 03:13:34 -08003005/* Case open detection */
3006
3007static ssize_t
3008clear_caseopen(struct device *dev, struct device_attribute *attr,
3009 const char *buf, size_t count)
3010{
3011 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003012 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3013 unsigned long val;
3014 u8 reg;
3015 int ret;
3016
3017 if (kstrtoul(buf, 10, &val) || val != 0)
3018 return -EINVAL;
3019
3020 mutex_lock(&data->update_lock);
3021
3022 /*
3023 * Use CR registers to clear caseopen status.
3024 * The CR registers are the same for all chips, and not all chips
3025 * support clearing the caseopen status through "regular" registers.
3026 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003027 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003028 if (ret) {
3029 count = ret;
3030 goto error;
3031 }
3032
Guenter Roeckdf612d52013-07-08 13:15:04 -07003033 superio_select(data->sioreg, NCT6775_LD_ACPI);
3034 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003035 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003036 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003037 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003038 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3039 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003040
3041 data->valid = false; /* Force cache refresh */
3042error:
3043 mutex_unlock(&data->update_lock);
3044 return count;
3045}
3046
Guenter Roeckf73cf632013-03-18 09:22:50 -07003047static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3048 clear_caseopen, INTRUSION_ALARM_BASE);
3049static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3050 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003051static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3052 store_beep, INTRUSION_ALARM_BASE);
3053static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3054 store_beep, INTRUSION_ALARM_BASE + 1);
3055static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3056 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003057
3058static umode_t nct6775_other_is_visible(struct kobject *kobj,
3059 struct attribute *attr, int index)
3060{
3061 struct device *dev = container_of(kobj, struct device, kobj);
3062 struct nct6775_data *data = dev_get_drvdata(dev);
3063
3064 if (index == 1 && !data->have_vid)
3065 return 0;
3066
3067 if (index == 2 || index == 3) {
3068 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
3069 return 0;
3070 }
3071
Guenter Roeck30846992013-06-24 22:21:59 -07003072 if (index == 4 || index == 5) {
3073 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
3074 return 0;
3075 }
3076
Guenter Roeckf73cf632013-03-18 09:22:50 -07003077 return attr->mode;
3078}
3079
3080/*
3081 * nct6775_other_is_visible uses the index into the following array
3082 * to determine if attributes should be created or not.
3083 * Any change in order or content must be matched.
3084 */
3085static struct attribute *nct6775_attributes_other[] = {
3086 &dev_attr_name.attr,
3087 &dev_attr_cpu0_vid.attr, /* 1 */
3088 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
3089 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
Guenter Roeck30846992013-06-24 22:21:59 -07003090 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 4 */
3091 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 5 */
3092 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 6 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003093
3094 NULL
3095};
3096
3097static const struct attribute_group nct6775_group_other = {
3098 .attrs = nct6775_attributes_other,
3099 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003100};
3101
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003102/*
3103 * Driver and device management
3104 */
3105
3106static void nct6775_device_remove_files(struct device *dev)
3107{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003108 struct nct6775_data *data = dev_get_drvdata(dev);
3109
Guenter Roeckf73cf632013-03-18 09:22:50 -07003110 if (data->group_pwm)
3111 sysfs_remove_group(&dev->kobj, data->group_pwm);
3112 if (data->group_in)
3113 sysfs_remove_group(&dev->kobj, data->group_in);
3114 if (data->group_fan)
3115 sysfs_remove_group(&dev->kobj, data->group_fan);
3116 if (data->group_temp)
3117 sysfs_remove_group(&dev->kobj, data->group_temp);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003118
Guenter Roeckf73cf632013-03-18 09:22:50 -07003119 sysfs_remove_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003120}
3121
3122/* Get the monitoring functions started */
3123static inline void nct6775_init_device(struct nct6775_data *data)
3124{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003125 int i;
3126 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003127
3128 /* Start monitoring if needed */
3129 if (data->REG_CONFIG) {
3130 tmp = nct6775_read_value(data, data->REG_CONFIG);
3131 if (!(tmp & 0x01))
3132 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3133 }
3134
Guenter Roeckaa136e52012-12-04 03:26:05 -08003135 /* Enable temperature sensors if needed */
3136 for (i = 0; i < NUM_TEMP; i++) {
3137 if (!(data->have_temp & (1 << i)))
3138 continue;
3139 if (!data->reg_temp_config[i])
3140 continue;
3141 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3142 if (tmp & 0x01)
3143 nct6775_write_value(data, data->reg_temp_config[i],
3144 tmp & 0xfe);
3145 }
3146
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003147 /* Enable VBAT monitoring if needed */
3148 tmp = nct6775_read_value(data, data->REG_VBAT);
3149 if (!(tmp & 0x01))
3150 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003151
3152 diode = nct6775_read_value(data, data->REG_DIODE);
3153
3154 for (i = 0; i < data->temp_fixed_num; i++) {
3155 if (!(data->have_temp_fixed & (1 << i)))
3156 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003157 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3158 data->temp_type[i]
3159 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003160 else /* thermistor */
3161 data->temp_type[i] = 4;
3162 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003163}
3164
Guenter Roeckf73cf632013-03-18 09:22:50 -07003165static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003166nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003167{
David Bartley578ab5f2013-06-24 22:28:28 -07003168 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3169 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003170 int sioreg = data->sioreg;
3171 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003172
3173 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3174 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003175 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003176
3177 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003178 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003179
3180 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003181 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003182 fan4min = false;
3183 fan5pin = false;
3184 fan6pin = false;
3185 pwm4pin = false;
3186 pwm5pin = false;
3187 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003188 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003189 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003190
Guenter Roeckdf612d52013-07-08 13:15:04 -07003191 superio_select(sioreg, NCT6775_LD_HWM);
3192 regval = superio_inb(sioreg, SIO_REG_ENABLE);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003193
3194 if (regval & 0x80)
3195 fan3pin = gpok;
3196 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003197 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003198
3199 if (regval & 0x40)
3200 fan4pin = gpok;
3201 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003202 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003203
3204 if (regval & 0x20)
3205 fan5pin = gpok;
3206 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003207 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003208
3209 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003210 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003211 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003212 pwm4pin = false;
3213 pwm5pin = false;
3214 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003215 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003216 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003217 fan3pin = !(regval & 0x80);
3218 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003219
3220 fan4pin = false;
3221 fan4min = false;
3222 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003223 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003224 pwm4pin = false;
3225 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003226 pwm6pin = false;
3227 } else { /* NCT6779D or NCT6791D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003228 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003229
3230 fan3pin = !(regval & (1 << 5));
3231 fan4pin = !(regval & (1 << 6));
3232 fan5pin = !(regval & (1 << 7));
3233
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003234 pwm3pin = !(regval & (1 << 0));
3235 pwm4pin = !(regval & (1 << 1));
3236 pwm5pin = !(regval & (1 << 2));
3237
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003238 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003239
3240 if (data->kind == nct6791) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003241 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003242 fan6pin = (regval & (1 << 1));
3243 pwm6pin = (regval & (1 << 0));
3244 } else { /* NCT6779D */
3245 fan6pin = false;
3246 pwm6pin = false;
3247 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003248 }
3249
David Bartley578ab5f2013-06-24 22:28:28 -07003250 /* fan 1 and 2 (0x03) are always present */
3251 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3252 (fan5pin << 4) | (fan6pin << 5);
3253 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3254 (fan5pin << 4);
3255 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3256 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003257}
3258
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003259static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3260 int *available, int *mask)
3261{
3262 int i;
3263 u8 src;
3264
3265 for (i = 0; i < data->pwm_num && *available; i++) {
3266 int index;
3267
3268 if (!regp[i])
3269 continue;
3270 src = nct6775_read_value(data, regp[i]);
3271 src &= 0x1f;
3272 if (!src || (*mask & (1 << src)))
3273 continue;
3274 if (src >= data->temp_label_num ||
3275 !strlen(data->temp_label[src]))
3276 continue;
3277
3278 index = __ffs(*available);
3279 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3280 *available &= ~(1 << index);
3281 *mask |= 1 << src;
3282 }
3283}
3284
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003285static int nct6775_probe(struct platform_device *pdev)
3286{
3287 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003288 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003289 struct nct6775_data *data;
3290 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003291 int i, s, err = 0;
3292 int src, mask, available;
3293 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3294 const u16 *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003295 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003296 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003297 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003298 struct attribute_group *group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003299
3300 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3301 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3302 DRVNAME))
3303 return -EBUSY;
3304
3305 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3306 GFP_KERNEL);
3307 if (!data)
3308 return -ENOMEM;
3309
3310 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003311 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003312 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003313 mutex_init(&data->update_lock);
3314 data->name = nct6775_device_names[data->kind];
3315 data->bank = 0xff; /* Force initial bank selection */
3316 platform_set_drvdata(pdev, data);
3317
3318 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003319 case nct6106:
3320 data->in_num = 9;
3321 data->pwm_num = 3;
3322 data->auto_pwm_num = 4;
3323 data->temp_fixed_num = 3;
3324 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003325 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003326
3327 data->fan_from_reg = fan_from_reg13;
3328 data->fan_from_reg_min = fan_from_reg13;
3329
3330 data->temp_label = nct6776_temp_label;
3331 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3332
3333 data->REG_VBAT = NCT6106_REG_VBAT;
3334 data->REG_DIODE = NCT6106_REG_DIODE;
3335 data->DIODE_MASK = NCT6106_DIODE_MASK;
3336 data->REG_VIN = NCT6106_REG_IN;
3337 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3338 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3339 data->REG_TARGET = NCT6106_REG_TARGET;
3340 data->REG_FAN = NCT6106_REG_FAN;
3341 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3342 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3343 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3344 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3345 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3346 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3347 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3348 data->REG_PWM[0] = NCT6106_REG_PWM;
3349 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3350 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3351 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3352 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3353 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3354 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3355 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3356 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3357 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3358 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3359 data->REG_CRITICAL_TEMP_TOLERANCE
3360 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3361 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3362 data->CRITICAL_PWM_ENABLE_MASK
3363 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3364 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3365 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3366 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3367 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3368 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3369 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3370 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3371 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3372 data->REG_ALARM = NCT6106_REG_ALARM;
3373 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003374 data->REG_BEEP = NCT6106_REG_BEEP;
3375 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003376
3377 reg_temp = NCT6106_REG_TEMP;
3378 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3379 reg_temp_over = NCT6106_REG_TEMP_OVER;
3380 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3381 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3382 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3383 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003384 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3385 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003386
3387 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003388 case nct6775:
3389 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003390 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003391 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003392 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003393 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003394 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003395 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003396
3397 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003398 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003399
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003400 data->fan_from_reg = fan_from_reg16;
3401 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003402 data->target_temp_mask = 0x7f;
3403 data->tolerance_mask = 0x0f;
3404 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003405
Guenter Roeckaa136e52012-12-04 03:26:05 -08003406 data->temp_label = nct6775_temp_label;
3407 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3408
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003409 data->REG_CONFIG = NCT6775_REG_CONFIG;
3410 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003411 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003412 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003413 data->REG_VIN = NCT6775_REG_IN;
3414 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3415 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003416 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003417 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003418 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003419 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003420 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003421 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003422 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3423 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3424 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003425 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003426 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3427 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3428 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3429 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003430 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003431 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3432 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3433 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003434 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3435 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3436 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3437 data->REG_CRITICAL_TEMP_TOLERANCE
3438 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003439 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3440 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003441 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003442 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3443 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3444 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3445 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003446 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003447 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003448
3449 reg_temp = NCT6775_REG_TEMP;
3450 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3451 reg_temp_over = NCT6775_REG_TEMP_OVER;
3452 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3453 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3454 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3455 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3456
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003457 break;
3458 case nct6776:
3459 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003460 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003461 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003462 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003463 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003464 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003465 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003466
3467 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003468 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003469
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003470 data->fan_from_reg = fan_from_reg13;
3471 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003472 data->target_temp_mask = 0xff;
3473 data->tolerance_mask = 0x07;
3474 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003475
Guenter Roeckaa136e52012-12-04 03:26:05 -08003476 data->temp_label = nct6776_temp_label;
3477 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3478
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003479 data->REG_CONFIG = NCT6775_REG_CONFIG;
3480 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003481 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003482 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003483 data->REG_VIN = NCT6775_REG_IN;
3484 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3485 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003486 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003487 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003488 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003489 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003490 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003491 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003492 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3493 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3494 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3495 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003496 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003497 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3498 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003499 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3500 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003501 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3502 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3503 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003504 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3505 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3506 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3507 data->REG_CRITICAL_TEMP_TOLERANCE
3508 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003509 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3510 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003511 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003512 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3513 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3514 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3515 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003516 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003517 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003518
3519 reg_temp = NCT6775_REG_TEMP;
3520 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3521 reg_temp_over = NCT6775_REG_TEMP_OVER;
3522 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3523 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3524 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3525 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3526
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003527 break;
3528 case nct6779:
3529 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003530 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003531 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003532 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003533 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003534 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003535 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003536
3537 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003538 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003539
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003540 data->fan_from_reg = fan_from_reg13;
3541 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003542 data->target_temp_mask = 0xff;
3543 data->tolerance_mask = 0x07;
3544 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003545
Guenter Roeckaa136e52012-12-04 03:26:05 -08003546 data->temp_label = nct6779_temp_label;
3547 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3548
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003549 data->REG_CONFIG = NCT6775_REG_CONFIG;
3550 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003551 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003552 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003553 data->REG_VIN = NCT6779_REG_IN;
3554 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3555 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003556 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003557 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003558 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003559 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003560 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003561 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003562 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3563 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3564 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3565 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003566 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003567 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3568 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003569 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3570 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003571 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3572 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3573 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003574 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3575 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3576 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3577 data->REG_CRITICAL_TEMP_TOLERANCE
3578 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003579 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3580 data->CRITICAL_PWM_ENABLE_MASK
3581 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3582 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003583 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3584 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003585 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003586 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3587 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3588 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3589 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003590 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003591 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003592
3593 reg_temp = NCT6779_REG_TEMP;
3594 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3595 reg_temp_over = NCT6779_REG_TEMP_OVER;
3596 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3597 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3598 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3599 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3600
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003601 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003602 case nct6791:
3603 data->in_num = 15;
3604 data->pwm_num = 6;
3605 data->auto_pwm_num = 4;
3606 data->has_fan_div = false;
3607 data->temp_fixed_num = 6;
3608 data->num_temp_alarms = 2;
3609 data->num_temp_beeps = 2;
3610
3611 data->ALARM_BITS = NCT6791_ALARM_BITS;
3612 data->BEEP_BITS = NCT6779_BEEP_BITS;
3613
3614 data->fan_from_reg = fan_from_reg13;
3615 data->fan_from_reg_min = fan_from_reg13;
3616 data->target_temp_mask = 0xff;
3617 data->tolerance_mask = 0x07;
3618 data->speed_tolerance_limit = 63;
3619
3620 data->temp_label = nct6779_temp_label;
3621 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3622
3623 data->REG_CONFIG = NCT6775_REG_CONFIG;
3624 data->REG_VBAT = NCT6775_REG_VBAT;
3625 data->REG_DIODE = NCT6775_REG_DIODE;
3626 data->DIODE_MASK = NCT6775_DIODE_MASK;
3627 data->REG_VIN = NCT6779_REG_IN;
3628 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3629 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3630 data->REG_TARGET = NCT6775_REG_TARGET;
3631 data->REG_FAN = NCT6779_REG_FAN;
3632 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3633 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3634 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3635 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3636 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3637 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3638 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3639 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3640 data->REG_PWM[0] = NCT6775_REG_PWM;
3641 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3642 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3643 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3644 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3645 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3646 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3647 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3648 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3649 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3650 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3651 data->REG_CRITICAL_TEMP_TOLERANCE
3652 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3653 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3654 data->CRITICAL_PWM_ENABLE_MASK
3655 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3656 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3657 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3658 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3659 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3660 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3661 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3662 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3663 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3664 data->REG_ALARM = NCT6791_REG_ALARM;
3665 data->REG_BEEP = NCT6776_REG_BEEP;
3666
3667 reg_temp = NCT6779_REG_TEMP;
3668 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3669 reg_temp_over = NCT6779_REG_TEMP_OVER;
3670 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3671 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3672 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3673 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3674
3675 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003676 default:
3677 return -ENODEV;
3678 }
3679 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003680 data->have_temp = 0;
3681
3682 /*
3683 * On some boards, not all available temperature sources are monitored,
3684 * even though some of the monitoring registers are unused.
3685 * Get list of unused monitoring registers, then detect if any fan
3686 * controls are configured to use unmonitored temperature sources.
3687 * If so, assign the unmonitored temperature sources to available
3688 * monitoring registers.
3689 */
3690 mask = 0;
3691 available = 0;
3692 for (i = 0; i < num_reg_temp; i++) {
3693 if (reg_temp[i] == 0)
3694 continue;
3695
3696 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3697 if (!src || (mask & (1 << src)))
3698 available |= 1 << i;
3699
3700 mask |= 1 << src;
3701 }
3702
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003703 /*
3704 * Now find unmonitored temperature registers and enable monitoring
3705 * if additional monitoring registers are available.
3706 */
3707 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3708 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3709
Guenter Roeckaa136e52012-12-04 03:26:05 -08003710 mask = 0;
3711 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3712 for (i = 0; i < num_reg_temp; i++) {
3713 if (reg_temp[i] == 0)
3714 continue;
3715
3716 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3717 if (!src || (mask & (1 << src)))
3718 continue;
3719
3720 if (src >= data->temp_label_num ||
3721 !strlen(data->temp_label[src])) {
3722 dev_info(dev,
3723 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3724 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3725 continue;
3726 }
3727
3728 mask |= 1 << src;
3729
3730 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3731 if (src <= data->temp_fixed_num) {
3732 data->have_temp |= 1 << (src - 1);
3733 data->have_temp_fixed |= 1 << (src - 1);
3734 data->reg_temp[0][src - 1] = reg_temp[i];
3735 data->reg_temp[1][src - 1] = reg_temp_over[i];
3736 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003737 if (reg_temp_crit_h && reg_temp_crit_h[i])
3738 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3739 else if (reg_temp_crit[src - 1])
3740 data->reg_temp[3][src - 1]
3741 = reg_temp_crit[src - 1];
3742 if (reg_temp_crit_l && reg_temp_crit_l[i])
3743 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003744 data->reg_temp_config[src - 1] = reg_temp_config[i];
3745 data->temp_src[src - 1] = src;
3746 continue;
3747 }
3748
3749 if (s >= NUM_TEMP)
3750 continue;
3751
3752 /* Use dynamic index for other sources */
3753 data->have_temp |= 1 << s;
3754 data->reg_temp[0][s] = reg_temp[i];
3755 data->reg_temp[1][s] = reg_temp_over[i];
3756 data->reg_temp[2][s] = reg_temp_hyst[i];
3757 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003758 if (reg_temp_crit_h && reg_temp_crit_h[i])
3759 data->reg_temp[3][s] = reg_temp_crit_h[i];
3760 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003761 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003762 if (reg_temp_crit_l && reg_temp_crit_l[i])
3763 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003764
3765 data->temp_src[s] = src;
3766 s++;
3767 }
3768
3769#ifdef USE_ALTERNATE
3770 /*
3771 * Go through the list of alternate temp registers and enable
3772 * if possible.
3773 * The temperature is already monitored if the respective bit in <mask>
3774 * is set.
3775 */
3776 for (i = 0; i < data->temp_label_num - 1; i++) {
3777 if (!reg_temp_alternate[i])
3778 continue;
3779 if (mask & (1 << (i + 1)))
3780 continue;
3781 if (i < data->temp_fixed_num) {
3782 if (data->have_temp & (1 << i))
3783 continue;
3784 data->have_temp |= 1 << i;
3785 data->have_temp_fixed |= 1 << i;
3786 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003787 if (i < num_reg_temp) {
3788 data->reg_temp[1][i] = reg_temp_over[i];
3789 data->reg_temp[2][i] = reg_temp_hyst[i];
3790 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003791 data->temp_src[i] = i + 1;
3792 continue;
3793 }
3794
3795 if (s >= NUM_TEMP) /* Abort if no more space */
3796 break;
3797
3798 data->have_temp |= 1 << s;
3799 data->reg_temp[0][s] = reg_temp_alternate[i];
3800 data->temp_src[s] = i + 1;
3801 s++;
3802 }
3803#endif /* USE_ALTERNATE */
3804
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003805 /* Initialize the chip */
3806 nct6775_init_device(data);
3807
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003808 err = superio_enter(sio_data->sioreg);
3809 if (err)
3810 return err;
3811
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003812 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3813 switch (data->kind) {
3814 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003815 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003816 break;
3817 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003818 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003819 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003820 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003821 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003822 case nct6791:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003823 break;
3824 }
3825
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003826 /*
3827 * Read VID value
3828 * We can get the VID input values directly at logical device D 0xe3.
3829 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003830 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003831 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3832 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3833 data->vrm = vid_which_vrm();
3834 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003835
3836 if (fan_debounce) {
3837 u8 tmp;
3838
3839 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3840 tmp = superio_inb(sio_data->sioreg,
3841 NCT6775_REG_CR_FAN_DEBOUNCE);
3842 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003843 case nct6106:
3844 tmp |= 0xe0;
3845 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003846 case nct6775:
3847 tmp |= 0x1e;
3848 break;
3849 case nct6776:
3850 case nct6779:
3851 tmp |= 0x3e;
3852 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003853 case nct6791:
3854 tmp |= 0x7e;
3855 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003856 }
3857 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3858 tmp);
3859 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3860 data->name);
3861 }
3862
Guenter Roeckdf612d52013-07-08 13:15:04 -07003863 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003864
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003865 superio_exit(sio_data->sioreg);
3866
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003867 /* Read fan clock dividers immediately */
3868 nct6775_init_fan_common(dev, data);
3869
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003870 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003871 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3872 data->pwm_num);
3873 if (IS_ERR(group)) {
3874 err = PTR_ERR(group);
3875 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003876 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003877 data->group_pwm = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003878
Guenter Roeckf73cf632013-03-18 09:22:50 -07003879 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3880 fls(data->have_in));
3881 if (IS_ERR(group)) {
3882 err = PTR_ERR(group);
3883 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003884 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003885 data->group_in = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003886
Guenter Roeckf73cf632013-03-18 09:22:50 -07003887 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3888 fls(data->has_fan));
3889 if (IS_ERR(group)) {
3890 err = PTR_ERR(group);
3891 goto exit_remove;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003892 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003893 data->group_fan = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003894
Guenter Roeckf73cf632013-03-18 09:22:50 -07003895 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3896 fls(data->have_temp));
3897 if (IS_ERR(group)) {
3898 err = PTR_ERR(group);
3899 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003900 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003901 data->group_temp = group;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003902
Guenter Roeckf73cf632013-03-18 09:22:50 -07003903 err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003904 if (err)
3905 goto exit_remove;
3906
3907 data->hwmon_dev = hwmon_device_register(dev);
3908 if (IS_ERR(data->hwmon_dev)) {
3909 err = PTR_ERR(data->hwmon_dev);
3910 goto exit_remove;
3911 }
3912
3913 return 0;
3914
3915exit_remove:
3916 nct6775_device_remove_files(dev);
3917 return err;
3918}
3919
3920static int nct6775_remove(struct platform_device *pdev)
3921{
3922 struct nct6775_data *data = platform_get_drvdata(pdev);
3923
3924 hwmon_device_unregister(data->hwmon_dev);
3925 nct6775_device_remove_files(&pdev->dev);
3926
3927 return 0;
3928}
3929
Guenter Roeck84d19d92012-12-04 08:01:39 -08003930#ifdef CONFIG_PM
3931static int nct6775_suspend(struct device *dev)
3932{
3933 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003934
3935 mutex_lock(&data->update_lock);
3936 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003937 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003938 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3939 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3940 }
3941 mutex_unlock(&data->update_lock);
3942
3943 return 0;
3944}
3945
3946static int nct6775_resume(struct device *dev)
3947{
3948 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003949 int i, j;
3950
3951 mutex_lock(&data->update_lock);
3952 data->bank = 0xff; /* Force initial bank selection */
3953
3954 /* Restore limits */
3955 for (i = 0; i < data->in_num; i++) {
3956 if (!(data->have_in & (1 << i)))
3957 continue;
3958
3959 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3960 data->in[i][1]);
3961 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3962 data->in[i][2]);
3963 }
3964
Guenter Roeckc409fd42013-04-09 05:04:00 -07003965 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003966 if (!(data->has_fan_min & (1 << i)))
3967 continue;
3968
3969 nct6775_write_value(data, data->REG_FAN_MIN[i],
3970 data->fan_min[i]);
3971 }
3972
3973 for (i = 0; i < NUM_TEMP; i++) {
3974 if (!(data->have_temp & (1 << i)))
3975 continue;
3976
Guenter Roeckc409fd42013-04-09 05:04:00 -07003977 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003978 if (data->reg_temp[j][i])
3979 nct6775_write_temp(data, data->reg_temp[j][i],
3980 data->temp[j][i]);
3981 }
3982
3983 /* Restore other settings */
3984 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003985 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003986 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3987 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3988 }
3989
3990 /* Force re-reading all values */
3991 data->valid = false;
3992 mutex_unlock(&data->update_lock);
3993
3994 return 0;
3995}
3996
3997static const struct dev_pm_ops nct6775_dev_pm_ops = {
3998 .suspend = nct6775_suspend,
3999 .resume = nct6775_resume,
Harald Judt374d1f92013-07-30 19:50:16 +02004000 .freeze = nct6775_suspend,
4001 .restore = nct6775_resume,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004002};
4003
4004#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4005#else
4006#define NCT6775_DEV_PM_OPS NULL
4007#endif /* CONFIG_PM */
4008
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004009static struct platform_driver nct6775_driver = {
4010 .driver = {
4011 .owner = THIS_MODULE,
4012 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004013 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004014 },
4015 .probe = nct6775_probe,
4016 .remove = nct6775_remove,
4017};
4018
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004019static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07004020 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004021 "NCT6775F",
4022 "NCT6776D/F",
4023 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07004024 "NCT6791D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004025};
4026
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004027/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004028static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004029{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004030 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004031 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004032 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004033
4034 err = superio_enter(sioaddr);
4035 if (err)
4036 return err;
4037
4038 if (force_id)
4039 val = force_id;
4040 else
4041 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4042 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4043 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07004044 case SIO_NCT6106_ID:
4045 sio_data->kind = nct6106;
4046 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004047 case SIO_NCT6775_ID:
4048 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004049 break;
4050 case SIO_NCT6776_ID:
4051 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004052 break;
4053 case SIO_NCT6779_ID:
4054 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004055 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004056 case SIO_NCT6791_ID:
4057 sio_data->kind = nct6791;
4058 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004059 default:
4060 if (val != 0xffff)
4061 pr_debug("unsupported chip ID: 0x%04x\n", val);
4062 superio_exit(sioaddr);
4063 return -ENODEV;
4064 }
4065
4066 /* We have a known chip, find the HWM I/O address */
4067 superio_select(sioaddr, NCT6775_LD_HWM);
4068 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4069 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004070 addr = val & IOREGION_ALIGNMENT;
4071 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004072 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4073 superio_exit(sioaddr);
4074 return -ENODEV;
4075 }
4076
4077 /* Activate logical device if needed */
4078 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4079 if (!(val & 0x01)) {
4080 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4081 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4082 }
David Bartley578ab5f2013-06-24 22:28:28 -07004083 if (sio_data->kind == nct6791) {
4084 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
4085 if (val & 0x10) {
4086 pr_info("Enabling hardware monitor logical device mappings.\n");
4087 superio_outb(sioaddr,
4088 NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
4089 val & ~0x10);
4090 }
4091 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004092
4093 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004094 pr_info("Found %s or compatible chip at %#x:%#x\n",
4095 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004096 sio_data->sioreg = sioaddr;
4097
Guenter Roeck698a7c22013-04-05 07:35:25 -07004098 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004099}
4100
4101/*
4102 * when Super-I/O functions move to a separate file, the Super-I/O
4103 * bus will manage the lifetime of the device and this module will only keep
4104 * track of the nct6775 driver. But since we platform_device_alloc(), we
4105 * must keep track of the device
4106 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004107static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004108
4109static int __init sensors_nct6775_init(void)
4110{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004111 int i, err;
4112 bool found = false;
4113 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004114 struct resource res;
4115 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004116 int sioaddr[2] = { 0x2e, 0x4e };
4117
4118 err = platform_driver_register(&nct6775_driver);
4119 if (err)
4120 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004121
4122 /*
4123 * initialize sio_data->kind and sio_data->sioreg.
4124 *
4125 * when Super-I/O functions move to a separate file, the Super-I/O
4126 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4127 * nct6775 hardware monitor, and call probe()
4128 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004129 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4130 address = nct6775_find(sioaddr[i], &sio_data);
4131 if (address <= 0)
4132 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004133
Guenter Roeck698a7c22013-04-05 07:35:25 -07004134 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004135
Guenter Roeck698a7c22013-04-05 07:35:25 -07004136 pdev[i] = platform_device_alloc(DRVNAME, address);
4137 if (!pdev[i]) {
4138 err = -ENOMEM;
4139 goto exit_device_put;
4140 }
4141
4142 err = platform_device_add_data(pdev[i], &sio_data,
4143 sizeof(struct nct6775_sio_data));
4144 if (err)
4145 goto exit_device_put;
4146
4147 memset(&res, 0, sizeof(res));
4148 res.name = DRVNAME;
4149 res.start = address + IOREGION_OFFSET;
4150 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4151 res.flags = IORESOURCE_IO;
4152
4153 err = acpi_check_resource_conflict(&res);
4154 if (err) {
4155 platform_device_put(pdev[i]);
4156 pdev[i] = NULL;
4157 continue;
4158 }
4159
4160 err = platform_device_add_resources(pdev[i], &res, 1);
4161 if (err)
4162 goto exit_device_put;
4163
4164 /* platform_device_add calls probe() */
4165 err = platform_device_add(pdev[i]);
4166 if (err)
4167 goto exit_device_put;
4168 }
4169 if (!found) {
4170 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004171 goto exit_unregister;
4172 }
4173
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004174 return 0;
4175
4176exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07004177 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4178 if (pdev[i])
4179 platform_device_put(pdev[i]);
4180 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004181exit_unregister:
4182 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004183 return err;
4184}
4185
4186static void __exit sensors_nct6775_exit(void)
4187{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004188 int i;
4189
4190 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4191 if (pdev[i])
4192 platform_device_unregister(pdev[i]);
4193 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004194 platform_driver_unregister(&nct6775_driver);
4195}
4196
4197MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4198MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4199MODULE_LICENSE("GPL");
4200
4201module_init(sensors_nct6775_init);
4202module_exit(sensors_nct6775_exit);