blob: b82fad48777794e9775ce29f55817263508d2a81 [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 }
Guenter Roeck45a5b3a2013-09-11 10:35:47 -07001460 if (i >= NUM_TEMP_FIXED ||
1461 !(data->have_temp_fixed & (1 << i)))
Guenter Roeckaa136e52012-12-04 03:26:05 -08001462 continue;
1463 data->temp_offset[i]
1464 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1465 }
1466
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001467 data->alarms = 0;
1468 for (i = 0; i < NUM_REG_ALARM; i++) {
1469 u8 alarm;
1470 if (!data->REG_ALARM[i])
1471 continue;
1472 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1473 data->alarms |= ((u64)alarm) << (i << 3);
1474 }
1475
Guenter Roeck30846992013-06-24 22:21:59 -07001476 data->beeps = 0;
1477 for (i = 0; i < NUM_REG_BEEP; i++) {
1478 u8 beep;
1479 if (!data->REG_BEEP[i])
1480 continue;
1481 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1482 data->beeps |= ((u64)beep) << (i << 3);
1483 }
1484
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001485 data->last_updated = jiffies;
1486 data->valid = true;
1487 }
1488
1489 mutex_unlock(&data->update_lock);
1490 return data;
1491}
1492
1493/*
1494 * Sysfs callback functions
1495 */
1496static ssize_t
1497show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1498{
1499 struct nct6775_data *data = nct6775_update_device(dev);
1500 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1501 int nr = sattr->nr;
1502 int index = sattr->index;
1503 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1504}
1505
1506static ssize_t
1507store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1508 size_t count)
1509{
1510 struct nct6775_data *data = dev_get_drvdata(dev);
1511 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1512 int nr = sattr->nr;
1513 int index = sattr->index;
1514 unsigned long val;
1515 int err = kstrtoul(buf, 10, &val);
1516 if (err < 0)
1517 return err;
1518 mutex_lock(&data->update_lock);
1519 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001520 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001521 data->in[nr][index]);
1522 mutex_unlock(&data->update_lock);
1523 return count;
1524}
1525
1526static ssize_t
1527show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1528{
1529 struct nct6775_data *data = nct6775_update_device(dev);
1530 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1531 int nr = data->ALARM_BITS[sattr->index];
1532 return sprintf(buf, "%u\n",
1533 (unsigned int)((data->alarms >> nr) & 0x01));
1534}
1535
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001536static int find_temp_source(struct nct6775_data *data, int index, int count)
1537{
1538 int source = data->temp_src[index];
1539 int nr;
1540
1541 for (nr = 0; nr < count; nr++) {
1542 int src;
1543
1544 src = nct6775_read_value(data,
1545 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1546 if (src == source)
1547 return nr;
1548 }
Guenter Roecke8ab5082013-09-11 10:32:18 -07001549 return -ENODEV;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001550}
1551
1552static ssize_t
1553show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1554{
1555 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1556 struct nct6775_data *data = nct6775_update_device(dev);
1557 unsigned int alarm = 0;
1558 int nr;
1559
1560 /*
1561 * For temperatures, there is no fixed mapping from registers to alarm
1562 * bits. Alarm bits are determined by the temperature source mapping.
1563 */
1564 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1565 if (nr >= 0) {
1566 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1567 alarm = (data->alarms >> bit) & 0x01;
1568 }
1569 return sprintf(buf, "%u\n", alarm);
1570}
1571
Guenter Roeck30846992013-06-24 22:21:59 -07001572static ssize_t
1573show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1574{
1575 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1576 struct nct6775_data *data = nct6775_update_device(dev);
1577 int nr = data->BEEP_BITS[sattr->index];
1578
1579 return sprintf(buf, "%u\n",
1580 (unsigned int)((data->beeps >> nr) & 0x01));
1581}
1582
1583static ssize_t
1584store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1585 size_t count)
1586{
1587 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1588 struct nct6775_data *data = dev_get_drvdata(dev);
1589 int nr = data->BEEP_BITS[sattr->index];
1590 int regindex = nr >> 3;
1591 unsigned long val;
1592
1593 int err = kstrtoul(buf, 10, &val);
1594 if (err < 0)
1595 return err;
1596 if (val > 1)
1597 return -EINVAL;
1598
1599 mutex_lock(&data->update_lock);
1600 if (val)
1601 data->beeps |= (1ULL << nr);
1602 else
1603 data->beeps &= ~(1ULL << nr);
1604 nct6775_write_value(data, data->REG_BEEP[regindex],
1605 (data->beeps >> (regindex << 3)) & 0xff);
1606 mutex_unlock(&data->update_lock);
1607 return count;
1608}
1609
1610static ssize_t
1611show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1612{
1613 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1614 struct nct6775_data *data = nct6775_update_device(dev);
1615 unsigned int beep = 0;
1616 int nr;
1617
1618 /*
1619 * For temperatures, there is no fixed mapping from registers to beep
1620 * enable bits. Beep enable bits are determined by the temperature
1621 * source mapping.
1622 */
1623 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1624 if (nr >= 0) {
1625 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1626 beep = (data->beeps >> bit) & 0x01;
1627 }
1628 return sprintf(buf, "%u\n", beep);
1629}
1630
1631static ssize_t
1632store_temp_beep(struct device *dev, struct device_attribute *attr,
1633 const char *buf, size_t count)
1634{
1635 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1636 struct nct6775_data *data = dev_get_drvdata(dev);
1637 int nr, bit, regindex;
1638 unsigned long val;
1639
1640 int err = kstrtoul(buf, 10, &val);
1641 if (err < 0)
1642 return err;
1643 if (val > 1)
1644 return -EINVAL;
1645
1646 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1647 if (nr < 0)
Guenter Roecke8ab5082013-09-11 10:32:18 -07001648 return nr;
Guenter Roeck30846992013-06-24 22:21:59 -07001649
1650 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1651 regindex = bit >> 3;
1652
1653 mutex_lock(&data->update_lock);
1654 if (val)
1655 data->beeps |= (1ULL << bit);
1656 else
1657 data->beeps &= ~(1ULL << bit);
1658 nct6775_write_value(data, data->REG_BEEP[regindex],
1659 (data->beeps >> (regindex << 3)) & 0xff);
1660 mutex_unlock(&data->update_lock);
1661
1662 return count;
1663}
1664
Guenter Roeckf73cf632013-03-18 09:22:50 -07001665static umode_t nct6775_in_is_visible(struct kobject *kobj,
1666 struct attribute *attr, int index)
1667{
1668 struct device *dev = container_of(kobj, struct device, kobj);
1669 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001670 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001671
Guenter Roeckf73cf632013-03-18 09:22:50 -07001672 if (!(data->have_in & (1 << in)))
1673 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001674
Guenter Roeckf73cf632013-03-18 09:22:50 -07001675 return attr->mode;
1676}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001677
Guenter Roeckf73cf632013-03-18 09:22:50 -07001678SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1679SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001680SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1681 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001682SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1683 store_in_reg, 0, 1);
1684SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1685 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001686
Guenter Roeckf73cf632013-03-18 09:22:50 -07001687/*
1688 * nct6775_in_is_visible uses the index into the following array
1689 * to determine if attributes should be created or not.
1690 * Any change in order or content must be matched.
1691 */
1692static struct sensor_device_template *nct6775_attributes_in_template[] = {
1693 &sensor_dev_template_in_input,
1694 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001695 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001696 &sensor_dev_template_in_min,
1697 &sensor_dev_template_in_max,
1698 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001699};
1700
Guenter Roeckf73cf632013-03-18 09:22:50 -07001701static struct sensor_template_group nct6775_in_template_group = {
1702 .templates = nct6775_attributes_in_template,
1703 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001704};
1705
1706static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001707show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1708{
1709 struct nct6775_data *data = nct6775_update_device(dev);
1710 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1711 int nr = sattr->index;
1712 return sprintf(buf, "%d\n", data->rpm[nr]);
1713}
1714
1715static ssize_t
1716show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1717{
1718 struct nct6775_data *data = nct6775_update_device(dev);
1719 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1720 int nr = sattr->index;
1721 return sprintf(buf, "%d\n",
1722 data->fan_from_reg_min(data->fan_min[nr],
1723 data->fan_div[nr]));
1724}
1725
1726static ssize_t
1727show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1728{
1729 struct nct6775_data *data = nct6775_update_device(dev);
1730 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1731 int nr = sattr->index;
1732 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1733}
1734
1735static ssize_t
1736store_fan_min(struct device *dev, struct device_attribute *attr,
1737 const char *buf, size_t count)
1738{
1739 struct nct6775_data *data = dev_get_drvdata(dev);
1740 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1741 int nr = sattr->index;
1742 unsigned long val;
1743 int err;
1744 unsigned int reg;
1745 u8 new_div;
1746
1747 err = kstrtoul(buf, 10, &val);
1748 if (err < 0)
1749 return err;
1750
1751 mutex_lock(&data->update_lock);
1752 if (!data->has_fan_div) {
1753 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1754 if (!val) {
1755 val = 0xff1f;
1756 } else {
1757 if (val > 1350000U)
1758 val = 135000U;
1759 val = 1350000U / val;
1760 val = (val & 0x1f) | ((val << 3) & 0xff00);
1761 }
1762 data->fan_min[nr] = val;
1763 goto write_min; /* Leave fan divider alone */
1764 }
1765 if (!val) {
1766 /* No min limit, alarm disabled */
1767 data->fan_min[nr] = 255;
1768 new_div = data->fan_div[nr]; /* No change */
1769 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1770 goto write_div;
1771 }
1772 reg = 1350000U / val;
1773 if (reg >= 128 * 255) {
1774 /*
1775 * Speed below this value cannot possibly be represented,
1776 * even with the highest divider (128)
1777 */
1778 data->fan_min[nr] = 254;
1779 new_div = 7; /* 128 == (1 << 7) */
1780 dev_warn(dev,
1781 "fan%u low limit %lu below minimum %u, set to minimum\n",
1782 nr + 1, val, data->fan_from_reg_min(254, 7));
1783 } else if (!reg) {
1784 /*
1785 * Speed above this value cannot possibly be represented,
1786 * even with the lowest divider (1)
1787 */
1788 data->fan_min[nr] = 1;
1789 new_div = 0; /* 1 == (1 << 0) */
1790 dev_warn(dev,
1791 "fan%u low limit %lu above maximum %u, set to maximum\n",
1792 nr + 1, val, data->fan_from_reg_min(1, 0));
1793 } else {
1794 /*
1795 * Automatically pick the best divider, i.e. the one such
1796 * that the min limit will correspond to a register value
1797 * in the 96..192 range
1798 */
1799 new_div = 0;
1800 while (reg > 192 && new_div < 7) {
1801 reg >>= 1;
1802 new_div++;
1803 }
1804 data->fan_min[nr] = reg;
1805 }
1806
1807write_div:
1808 /*
1809 * Write both the fan clock divider (if it changed) and the new
1810 * fan min (unconditionally)
1811 */
1812 if (new_div != data->fan_div[nr]) {
1813 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1814 nr + 1, div_from_reg(data->fan_div[nr]),
1815 div_from_reg(new_div));
1816 data->fan_div[nr] = new_div;
1817 nct6775_write_fan_div_common(data, nr);
1818 /* Give the chip time to sample a new speed value */
1819 data->last_updated = jiffies;
1820 }
1821
1822write_min:
1823 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1824 mutex_unlock(&data->update_lock);
1825
1826 return count;
1827}
1828
Guenter Roeck5c25d952012-12-11 07:29:06 -08001829static ssize_t
1830show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1831{
1832 struct nct6775_data *data = nct6775_update_device(dev);
1833 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1834 int p = data->fan_pulses[sattr->index];
1835
1836 return sprintf(buf, "%d\n", p ? : 4);
1837}
1838
1839static ssize_t
1840store_fan_pulses(struct device *dev, struct device_attribute *attr,
1841 const char *buf, size_t count)
1842{
1843 struct nct6775_data *data = dev_get_drvdata(dev);
1844 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1845 int nr = sattr->index;
1846 unsigned long val;
1847 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001848 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001849
1850 err = kstrtoul(buf, 10, &val);
1851 if (err < 0)
1852 return err;
1853
1854 if (val > 4)
1855 return -EINVAL;
1856
1857 mutex_lock(&data->update_lock);
1858 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001859 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1860 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1861 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1862 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001863 mutex_unlock(&data->update_lock);
1864
1865 return count;
1866}
1867
Guenter Roeckf73cf632013-03-18 09:22:50 -07001868static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1869 struct attribute *attr, int index)
1870{
1871 struct device *dev = container_of(kobj, struct device, kobj);
1872 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001873 int fan = index / 6; /* fan index */
1874 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001875
1876 if (!(data->has_fan & (1 << fan)))
1877 return 0;
1878
1879 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1880 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001881 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001882 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001883 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1884 return 0;
1885 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001886 return 0;
1887
1888 return attr->mode;
1889}
1890
1891SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1892SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1893 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001894SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1895 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001896SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1897 store_fan_pulses, 0);
1898SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1899 store_fan_min, 0);
1900SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1901
1902/*
1903 * nct6775_fan_is_visible uses the index into the following array
1904 * to determine if attributes should be created or not.
1905 * Any change in order or content must be matched.
1906 */
1907static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1908 &sensor_dev_template_fan_input,
1909 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001910 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001911 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001912 &sensor_dev_template_fan_min, /* 4 */
1913 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001914 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001915};
1916
Guenter Roeckf73cf632013-03-18 09:22:50 -07001917static struct sensor_template_group nct6775_fan_template_group = {
1918 .templates = nct6775_attributes_fan_template,
1919 .is_visible = nct6775_fan_is_visible,
1920 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001921};
1922
1923static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001924show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1925{
1926 struct nct6775_data *data = nct6775_update_device(dev);
1927 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1928 int nr = sattr->index;
1929 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1930}
1931
1932static ssize_t
1933show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1934{
1935 struct nct6775_data *data = nct6775_update_device(dev);
1936 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1937 int nr = sattr->nr;
1938 int index = sattr->index;
1939
1940 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1941}
1942
1943static ssize_t
1944store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1945 size_t count)
1946{
1947 struct nct6775_data *data = dev_get_drvdata(dev);
1948 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1949 int nr = sattr->nr;
1950 int index = sattr->index;
1951 int err;
1952 long val;
1953
1954 err = kstrtol(buf, 10, &val);
1955 if (err < 0)
1956 return err;
1957
1958 mutex_lock(&data->update_lock);
1959 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1960 nct6775_write_temp(data, data->reg_temp[index][nr],
1961 data->temp[index][nr]);
1962 mutex_unlock(&data->update_lock);
1963 return count;
1964}
1965
1966static ssize_t
1967show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1968{
1969 struct nct6775_data *data = nct6775_update_device(dev);
1970 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1971
1972 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1973}
1974
1975static ssize_t
1976store_temp_offset(struct device *dev, struct device_attribute *attr,
1977 const char *buf, size_t count)
1978{
1979 struct nct6775_data *data = dev_get_drvdata(dev);
1980 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1981 int nr = sattr->index;
1982 long val;
1983 int err;
1984
1985 err = kstrtol(buf, 10, &val);
1986 if (err < 0)
1987 return err;
1988
1989 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1990
1991 mutex_lock(&data->update_lock);
1992 data->temp_offset[nr] = val;
1993 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1994 mutex_unlock(&data->update_lock);
1995
1996 return count;
1997}
1998
1999static ssize_t
2000show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
2001{
2002 struct nct6775_data *data = nct6775_update_device(dev);
2003 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2004 int nr = sattr->index;
2005 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2006}
2007
2008static ssize_t
2009store_temp_type(struct device *dev, struct device_attribute *attr,
2010 const char *buf, size_t count)
2011{
2012 struct nct6775_data *data = nct6775_update_device(dev);
2013 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2014 int nr = sattr->index;
2015 unsigned long val;
2016 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002017 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002018
2019 err = kstrtoul(buf, 10, &val);
2020 if (err < 0)
2021 return err;
2022
2023 if (val != 1 && val != 3 && val != 4)
2024 return -EINVAL;
2025
2026 mutex_lock(&data->update_lock);
2027
2028 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002029 vbit = 0x02 << nr;
2030 dbit = data->DIODE_MASK << nr;
2031 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2032 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002033 switch (val) {
2034 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002035 vbat |= vbit;
2036 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002037 break;
2038 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002039 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002040 break;
2041 case 4: /* thermistor */
2042 break;
2043 }
2044 nct6775_write_value(data, data->REG_VBAT, vbat);
2045 nct6775_write_value(data, data->REG_DIODE, diode);
2046
2047 mutex_unlock(&data->update_lock);
2048 return count;
2049}
2050
Guenter Roeckf73cf632013-03-18 09:22:50 -07002051static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2052 struct attribute *attr, int index)
2053{
2054 struct device *dev = container_of(kobj, struct device, kobj);
2055 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002056 int temp = index / 10; /* temp index */
2057 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002058
2059 if (!(data->have_temp & (1 << temp)))
2060 return 0;
2061
2062 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2063 return 0; /* alarm */
2064
Guenter Roeck30846992013-06-24 22:21:59 -07002065 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2066 return 0; /* beep */
2067
2068 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002069 return 0;
2070
Guenter Roeck30846992013-06-24 22:21:59 -07002071 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002072 return 0;
2073
Guenter Roeck30846992013-06-24 22:21:59 -07002074 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002075 return 0;
2076
Guenter Roeck30846992013-06-24 22:21:59 -07002077 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002078 return 0;
2079
2080 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002081 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002082 return 0;
2083
2084 return attr->mode;
2085}
2086
2087SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2088SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2089SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2090 store_temp, 0, 1);
2091SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2092 show_temp, store_temp, 0, 2);
2093SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2094 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002095SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2096 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002097SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2098 show_temp_offset, store_temp_offset, 0);
2099SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2100 store_temp_type, 0);
2101SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002102SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2103 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002104
2105/*
2106 * nct6775_temp_is_visible uses the index into the following array
2107 * to determine if attributes should be created or not.
2108 * Any change in order or content must be matched.
2109 */
2110static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2111 &sensor_dev_template_temp_input,
2112 &sensor_dev_template_temp_label,
2113 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002114 &sensor_dev_template_temp_beep, /* 3 */
2115 &sensor_dev_template_temp_max, /* 4 */
2116 &sensor_dev_template_temp_max_hyst, /* 5 */
2117 &sensor_dev_template_temp_crit, /* 6 */
2118 &sensor_dev_template_temp_lcrit, /* 7 */
2119 &sensor_dev_template_temp_offset, /* 8 */
2120 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002121 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002122};
2123
Guenter Roeckf73cf632013-03-18 09:22:50 -07002124static struct sensor_template_group nct6775_temp_template_group = {
2125 .templates = nct6775_attributes_temp_template,
2126 .is_visible = nct6775_temp_is_visible,
2127 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002128};
2129
Guenter Roeckaa136e52012-12-04 03:26:05 -08002130static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002131show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2132{
2133 struct nct6775_data *data = nct6775_update_device(dev);
2134 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2135
2136 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2137}
2138
2139static ssize_t
2140store_pwm_mode(struct device *dev, struct device_attribute *attr,
2141 const char *buf, size_t count)
2142{
2143 struct nct6775_data *data = dev_get_drvdata(dev);
2144 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2145 int nr = sattr->index;
2146 unsigned long val;
2147 int err;
2148 u8 reg;
2149
2150 err = kstrtoul(buf, 10, &val);
2151 if (err < 0)
2152 return err;
2153
2154 if (val > 1)
2155 return -EINVAL;
2156
2157 /* Setting DC mode is not supported for all chips/channels */
2158 if (data->REG_PWM_MODE[nr] == 0) {
2159 if (val)
2160 return -EINVAL;
2161 return count;
2162 }
2163
2164 mutex_lock(&data->update_lock);
2165 data->pwm_mode[nr] = val;
2166 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2167 reg &= ~data->PWM_MODE_MASK[nr];
2168 if (val)
2169 reg |= data->PWM_MODE_MASK[nr];
2170 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2171 mutex_unlock(&data->update_lock);
2172 return count;
2173}
2174
2175static ssize_t
2176show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2177{
2178 struct nct6775_data *data = nct6775_update_device(dev);
2179 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2180 int nr = sattr->nr;
2181 int index = sattr->index;
2182 int pwm;
2183
2184 /*
2185 * For automatic fan control modes, show current pwm readings.
2186 * Otherwise, show the configured value.
2187 */
2188 if (index == 0 && data->pwm_enable[nr] > manual)
2189 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2190 else
2191 pwm = data->pwm[index][nr];
2192
2193 return sprintf(buf, "%d\n", pwm);
2194}
2195
2196static ssize_t
2197store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2198 size_t count)
2199{
2200 struct nct6775_data *data = dev_get_drvdata(dev);
2201 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2202 int nr = sattr->nr;
2203 int index = sattr->index;
2204 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002205 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2206 int maxval[7]
2207 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002208 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002209 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002210
2211 err = kstrtoul(buf, 10, &val);
2212 if (err < 0)
2213 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002214 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002215
2216 mutex_lock(&data->update_lock);
2217 data->pwm[index][nr] = val;
2218 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002219 if (index == 2) { /* floor: disable if val == 0 */
2220 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2221 reg &= 0x7f;
2222 if (val)
2223 reg |= 0x80;
2224 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2225 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002226 mutex_unlock(&data->update_lock);
2227 return count;
2228}
2229
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002230/* Returns 0 if OK, -EINVAL otherwise */
2231static int check_trip_points(struct nct6775_data *data, int nr)
2232{
2233 int i;
2234
2235 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2236 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2237 return -EINVAL;
2238 }
2239 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2240 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2241 return -EINVAL;
2242 }
2243 /* validate critical temperature and pwm if enabled (pwm > 0) */
2244 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2245 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2246 data->auto_temp[nr][data->auto_pwm_num] ||
2247 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2248 data->auto_pwm[nr][data->auto_pwm_num])
2249 return -EINVAL;
2250 }
2251 return 0;
2252}
2253
2254static void pwm_update_registers(struct nct6775_data *data, int nr)
2255{
2256 u8 reg;
2257
2258 switch (data->pwm_enable[nr]) {
2259 case off:
2260 case manual:
2261 break;
2262 case speed_cruise:
2263 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2264 reg = (reg & ~data->tolerance_mask) |
2265 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2266 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2267 nct6775_write_value(data, data->REG_TARGET[nr],
2268 data->target_speed[nr] & 0xff);
2269 if (data->REG_TOLERANCE_H) {
2270 reg = (data->target_speed[nr] >> 8) & 0x0f;
2271 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2272 nct6775_write_value(data,
2273 data->REG_TOLERANCE_H[nr],
2274 reg);
2275 }
2276 break;
2277 case thermal_cruise:
2278 nct6775_write_value(data, data->REG_TARGET[nr],
2279 data->target_temp[nr]);
2280 /* intentional */
2281 default:
2282 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2283 reg = (reg & ~data->tolerance_mask) |
2284 data->temp_tolerance[0][nr];
2285 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2286 break;
2287 }
2288}
2289
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002290static ssize_t
2291show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2292{
2293 struct nct6775_data *data = nct6775_update_device(dev);
2294 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2295
2296 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2297}
2298
2299static ssize_t
2300store_pwm_enable(struct device *dev, struct device_attribute *attr,
2301 const char *buf, size_t count)
2302{
2303 struct nct6775_data *data = dev_get_drvdata(dev);
2304 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2305 int nr = sattr->index;
2306 unsigned long val;
2307 int err;
2308 u16 reg;
2309
2310 err = kstrtoul(buf, 10, &val);
2311 if (err < 0)
2312 return err;
2313
2314 if (val > sf4)
2315 return -EINVAL;
2316
2317 if (val == sf3 && data->kind != nct6775)
2318 return -EINVAL;
2319
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002320 if (val == sf4 && check_trip_points(data, nr)) {
2321 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2322 dev_err(dev, "Adjust trip points and try again\n");
2323 return -EINVAL;
2324 }
2325
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002326 mutex_lock(&data->update_lock);
2327 data->pwm_enable[nr] = val;
2328 if (val == off) {
2329 /*
2330 * turn off pwm control: select manual mode, set pwm to maximum
2331 */
2332 data->pwm[0][nr] = 255;
2333 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2334 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002335 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002336 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2337 reg &= 0x0f;
2338 reg |= pwm_enable_to_reg(val) << 4;
2339 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2340 mutex_unlock(&data->update_lock);
2341 return count;
2342}
2343
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002344static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002345show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002346{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002347 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002348
2349 for (i = 0; i < NUM_TEMP; i++) {
2350 if (!(data->have_temp & (1 << i)))
2351 continue;
2352 if (src == data->temp_src[i]) {
2353 sel = i + 1;
2354 break;
2355 }
2356 }
2357
2358 return sprintf(buf, "%d\n", sel);
2359}
2360
2361static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002362show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2363{
2364 struct nct6775_data *data = nct6775_update_device(dev);
2365 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2366 int index = sattr->index;
2367
2368 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2369}
2370
2371static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002372store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2373 const char *buf, size_t count)
2374{
2375 struct nct6775_data *data = nct6775_update_device(dev);
2376 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2377 int nr = sattr->index;
2378 unsigned long val;
2379 int err, reg, src;
2380
2381 err = kstrtoul(buf, 10, &val);
2382 if (err < 0)
2383 return err;
2384 if (val == 0 || val > NUM_TEMP)
2385 return -EINVAL;
2386 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2387 return -EINVAL;
2388
2389 mutex_lock(&data->update_lock);
2390 src = data->temp_src[val - 1];
2391 data->pwm_temp_sel[nr] = src;
2392 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2393 reg &= 0xe0;
2394 reg |= src;
2395 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2396 mutex_unlock(&data->update_lock);
2397
2398 return count;
2399}
2400
2401static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002402show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2403 char *buf)
2404{
2405 struct nct6775_data *data = nct6775_update_device(dev);
2406 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2407 int index = sattr->index;
2408
2409 return show_pwm_temp_sel_common(data, buf,
2410 data->pwm_weight_temp_sel[index]);
2411}
2412
2413static ssize_t
2414store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2415 const char *buf, size_t count)
2416{
2417 struct nct6775_data *data = nct6775_update_device(dev);
2418 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2419 int nr = sattr->index;
2420 unsigned long val;
2421 int err, reg, src;
2422
2423 err = kstrtoul(buf, 10, &val);
2424 if (err < 0)
2425 return err;
2426 if (val > NUM_TEMP)
2427 return -EINVAL;
2428 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2429 !data->temp_src[val - 1]))
2430 return -EINVAL;
2431
2432 mutex_lock(&data->update_lock);
2433 if (val) {
2434 src = data->temp_src[val - 1];
2435 data->pwm_weight_temp_sel[nr] = src;
2436 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2437 reg &= 0xe0;
2438 reg |= (src | 0x80);
2439 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2440 } else {
2441 data->pwm_weight_temp_sel[nr] = 0;
2442 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2443 reg &= 0x7f;
2444 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2445 }
2446 mutex_unlock(&data->update_lock);
2447
2448 return count;
2449}
2450
2451static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002452show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2453{
2454 struct nct6775_data *data = nct6775_update_device(dev);
2455 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2456
2457 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2458}
2459
2460static ssize_t
2461store_target_temp(struct device *dev, struct device_attribute *attr,
2462 const char *buf, size_t count)
2463{
2464 struct nct6775_data *data = dev_get_drvdata(dev);
2465 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2466 int nr = sattr->index;
2467 unsigned long val;
2468 int err;
2469
2470 err = kstrtoul(buf, 10, &val);
2471 if (err < 0)
2472 return err;
2473
2474 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2475 data->target_temp_mask);
2476
2477 mutex_lock(&data->update_lock);
2478 data->target_temp[nr] = val;
2479 pwm_update_registers(data, nr);
2480 mutex_unlock(&data->update_lock);
2481 return count;
2482}
2483
2484static ssize_t
2485show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2486{
2487 struct nct6775_data *data = nct6775_update_device(dev);
2488 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2489 int nr = sattr->index;
2490
2491 return sprintf(buf, "%d\n",
2492 fan_from_reg16(data->target_speed[nr],
2493 data->fan_div[nr]));
2494}
2495
2496static ssize_t
2497store_target_speed(struct device *dev, struct device_attribute *attr,
2498 const char *buf, size_t count)
2499{
2500 struct nct6775_data *data = dev_get_drvdata(dev);
2501 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2502 int nr = sattr->index;
2503 unsigned long val;
2504 int err;
2505 u16 speed;
2506
2507 err = kstrtoul(buf, 10, &val);
2508 if (err < 0)
2509 return err;
2510
2511 val = clamp_val(val, 0, 1350000U);
2512 speed = fan_to_reg(val, data->fan_div[nr]);
2513
2514 mutex_lock(&data->update_lock);
2515 data->target_speed[nr] = speed;
2516 pwm_update_registers(data, nr);
2517 mutex_unlock(&data->update_lock);
2518 return count;
2519}
2520
2521static ssize_t
2522show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2523 char *buf)
2524{
2525 struct nct6775_data *data = nct6775_update_device(dev);
2526 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2527 int nr = sattr->nr;
2528 int index = sattr->index;
2529
2530 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2531}
2532
2533static ssize_t
2534store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2535 const char *buf, size_t count)
2536{
2537 struct nct6775_data *data = dev_get_drvdata(dev);
2538 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2539 int nr = sattr->nr;
2540 int index = sattr->index;
2541 unsigned long val;
2542 int err;
2543
2544 err = kstrtoul(buf, 10, &val);
2545 if (err < 0)
2546 return err;
2547
2548 /* Limit tolerance as needed */
2549 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2550
2551 mutex_lock(&data->update_lock);
2552 data->temp_tolerance[index][nr] = val;
2553 if (index)
2554 pwm_update_registers(data, nr);
2555 else
2556 nct6775_write_value(data,
2557 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2558 val);
2559 mutex_unlock(&data->update_lock);
2560 return count;
2561}
2562
2563/*
2564 * Fan speed tolerance is a tricky beast, since the associated register is
2565 * a tick counter, but the value is reported and configured as rpm.
2566 * Compute resulting low and high rpm values and report the difference.
2567 */
2568static ssize_t
2569show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2570 char *buf)
2571{
2572 struct nct6775_data *data = nct6775_update_device(dev);
2573 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2574 int nr = sattr->index;
2575 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2576 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2577 int tolerance;
2578
2579 if (low <= 0)
2580 low = 1;
2581 if (high > 0xffff)
2582 high = 0xffff;
2583 if (high < low)
2584 high = low;
2585
2586 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2587 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2588
2589 return sprintf(buf, "%d\n", tolerance);
2590}
2591
2592static ssize_t
2593store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2594 const char *buf, size_t count)
2595{
2596 struct nct6775_data *data = dev_get_drvdata(dev);
2597 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2598 int nr = sattr->index;
2599 unsigned long val;
2600 int err;
2601 int low, high;
2602
2603 err = kstrtoul(buf, 10, &val);
2604 if (err < 0)
2605 return err;
2606
2607 high = fan_from_reg16(data->target_speed[nr],
2608 data->fan_div[nr]) + val;
2609 low = fan_from_reg16(data->target_speed[nr],
2610 data->fan_div[nr]) - val;
2611 if (low <= 0)
2612 low = 1;
2613 if (high < low)
2614 high = low;
2615
2616 val = (fan_to_reg(low, data->fan_div[nr]) -
2617 fan_to_reg(high, data->fan_div[nr])) / 2;
2618
2619 /* Limit tolerance as needed */
2620 val = clamp_val(val, 0, data->speed_tolerance_limit);
2621
2622 mutex_lock(&data->update_lock);
2623 data->target_speed_tolerance[nr] = val;
2624 pwm_update_registers(data, nr);
2625 mutex_unlock(&data->update_lock);
2626 return count;
2627}
2628
Guenter Roeckf73cf632013-03-18 09:22:50 -07002629SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2630SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2631 store_pwm_mode, 0);
2632SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2633 store_pwm_enable, 0);
2634SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2635 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2636SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2637 show_target_temp, store_target_temp, 0);
2638SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2639 show_target_speed, store_target_speed, 0);
2640SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2641 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002642
2643/* Smart Fan registers */
2644
2645static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002646show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2647{
2648 struct nct6775_data *data = nct6775_update_device(dev);
2649 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2650 int nr = sattr->nr;
2651 int index = sattr->index;
2652
2653 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2654}
2655
2656static ssize_t
2657store_weight_temp(struct device *dev, struct device_attribute *attr,
2658 const char *buf, size_t count)
2659{
2660 struct nct6775_data *data = dev_get_drvdata(dev);
2661 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2662 int nr = sattr->nr;
2663 int index = sattr->index;
2664 unsigned long val;
2665 int err;
2666
2667 err = kstrtoul(buf, 10, &val);
2668 if (err < 0)
2669 return err;
2670
2671 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2672
2673 mutex_lock(&data->update_lock);
2674 data->weight_temp[index][nr] = val;
2675 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2676 mutex_unlock(&data->update_lock);
2677 return count;
2678}
2679
Guenter Roeckf73cf632013-03-18 09:22:50 -07002680SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2681 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2682SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2683 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2684SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2685 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2686SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2687 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2688SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2689 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2690SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2691 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002692
2693static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002694show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2695{
2696 struct nct6775_data *data = nct6775_update_device(dev);
2697 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2698 int nr = sattr->nr;
2699 int index = sattr->index;
2700
2701 return sprintf(buf, "%d\n",
2702 step_time_from_reg(data->fan_time[index][nr],
2703 data->pwm_mode[nr]));
2704}
2705
2706static ssize_t
2707store_fan_time(struct device *dev, struct device_attribute *attr,
2708 const char *buf, size_t count)
2709{
2710 struct nct6775_data *data = dev_get_drvdata(dev);
2711 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2712 int nr = sattr->nr;
2713 int index = sattr->index;
2714 unsigned long val;
2715 int err;
2716
2717 err = kstrtoul(buf, 10, &val);
2718 if (err < 0)
2719 return err;
2720
2721 val = step_time_to_reg(val, data->pwm_mode[nr]);
2722 mutex_lock(&data->update_lock);
2723 data->fan_time[index][nr] = val;
2724 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2725 mutex_unlock(&data->update_lock);
2726 return count;
2727}
2728
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002729static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002730show_name(struct device *dev, struct device_attribute *attr, char *buf)
2731{
2732 struct nct6775_data *data = dev_get_drvdata(dev);
2733
2734 return sprintf(buf, "%s\n", data->name);
2735}
2736
2737static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2738
2739static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002740show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2741{
2742 struct nct6775_data *data = nct6775_update_device(dev);
2743 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2744
2745 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2746}
2747
2748static ssize_t
2749store_auto_pwm(struct device *dev, struct device_attribute *attr,
2750 const char *buf, size_t count)
2751{
2752 struct nct6775_data *data = dev_get_drvdata(dev);
2753 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2754 int nr = sattr->nr;
2755 int point = sattr->index;
2756 unsigned long val;
2757 int err;
2758 u8 reg;
2759
2760 err = kstrtoul(buf, 10, &val);
2761 if (err < 0)
2762 return err;
2763 if (val > 255)
2764 return -EINVAL;
2765
2766 if (point == data->auto_pwm_num) {
2767 if (data->kind != nct6775 && !val)
2768 return -EINVAL;
2769 if (data->kind != nct6779 && val)
2770 val = 0xff;
2771 }
2772
2773 mutex_lock(&data->update_lock);
2774 data->auto_pwm[nr][point] = val;
2775 if (point < data->auto_pwm_num) {
2776 nct6775_write_value(data,
2777 NCT6775_AUTO_PWM(data, nr, point),
2778 data->auto_pwm[nr][point]);
2779 } else {
2780 switch (data->kind) {
2781 case nct6775:
2782 /* disable if needed (pwm == 0) */
2783 reg = nct6775_read_value(data,
2784 NCT6775_REG_CRITICAL_ENAB[nr]);
2785 if (val)
2786 reg |= 0x02;
2787 else
2788 reg &= ~0x02;
2789 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2790 reg);
2791 break;
2792 case nct6776:
2793 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002794 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002795 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002796 case nct6791:
Guenter Roeck6c009502012-07-01 08:23:15 -07002797 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002798 val);
2799 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002800 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002801 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002802 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002803 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002804 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002805 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002806 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002807 reg);
2808 break;
2809 }
2810 }
2811 mutex_unlock(&data->update_lock);
2812 return count;
2813}
2814
2815static ssize_t
2816show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2817{
2818 struct nct6775_data *data = nct6775_update_device(dev);
2819 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2820 int nr = sattr->nr;
2821 int point = sattr->index;
2822
2823 /*
2824 * We don't know for sure if the temperature is signed or unsigned.
2825 * Assume it is unsigned.
2826 */
2827 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2828}
2829
2830static ssize_t
2831store_auto_temp(struct device *dev, struct device_attribute *attr,
2832 const char *buf, size_t count)
2833{
2834 struct nct6775_data *data = dev_get_drvdata(dev);
2835 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2836 int nr = sattr->nr;
2837 int point = sattr->index;
2838 unsigned long val;
2839 int err;
2840
2841 err = kstrtoul(buf, 10, &val);
2842 if (err)
2843 return err;
2844 if (val > 255000)
2845 return -EINVAL;
2846
2847 mutex_lock(&data->update_lock);
2848 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2849 if (point < data->auto_pwm_num) {
2850 nct6775_write_value(data,
2851 NCT6775_AUTO_TEMP(data, nr, point),
2852 data->auto_temp[nr][point]);
2853 } else {
2854 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2855 data->auto_temp[nr][point]);
2856 }
2857 mutex_unlock(&data->update_lock);
2858 return count;
2859}
2860
Guenter Roeckf73cf632013-03-18 09:22:50 -07002861static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2862 struct attribute *attr, int index)
2863{
2864 struct device *dev = container_of(kobj, struct device, kobj);
2865 struct nct6775_data *data = dev_get_drvdata(dev);
2866 int pwm = index / 36; /* pwm index */
2867 int nr = index % 36; /* attribute index */
2868
2869 if (!(data->has_pwm & (1 << pwm)))
2870 return 0;
2871
2872 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2873 return 0;
2874 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2875 return 0;
2876 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2877 return 0;
2878
2879 if (nr >= 22 && nr <= 35) { /* auto point */
2880 int api = (nr - 22) / 2; /* auto point index */
2881
2882 if (api > data->auto_pwm_num)
2883 return 0;
2884 }
2885 return attr->mode;
2886}
2887
2888SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2889 show_fan_time, store_fan_time, 0, 0);
2890SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2891 show_fan_time, store_fan_time, 0, 1);
2892SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2893 show_fan_time, store_fan_time, 0, 2);
2894SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2895 store_pwm, 0, 1);
2896SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2897 store_pwm, 0, 2);
2898SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2899 show_temp_tolerance, store_temp_tolerance, 0, 0);
2900SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2901 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2902 0, 1);
2903
2904SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2905 0, 3);
2906
2907SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2908 store_pwm, 0, 4);
2909
2910SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2911 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2912SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2913 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2914
2915SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2916 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2917SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2918 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2919
2920SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2921 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2922SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2923 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2924
2925SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2926 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2927SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2928 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2929
2930SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2931 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2932SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2933 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2934
2935SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2936 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2937SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2938 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2939
2940SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2941 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2942SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2943 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2944
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002945/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002946 * nct6775_pwm_is_visible uses the index into the following array
2947 * to determine if attributes should be created or not.
2948 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002949 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002950static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2951 &sensor_dev_template_pwm,
2952 &sensor_dev_template_pwm_mode,
2953 &sensor_dev_template_pwm_enable,
2954 &sensor_dev_template_pwm_temp_sel,
2955 &sensor_dev_template_pwm_temp_tolerance,
2956 &sensor_dev_template_pwm_crit_temp_tolerance,
2957 &sensor_dev_template_pwm_target_temp,
2958 &sensor_dev_template_fan_target,
2959 &sensor_dev_template_fan_tolerance,
2960 &sensor_dev_template_pwm_stop_time,
2961 &sensor_dev_template_pwm_step_up_time,
2962 &sensor_dev_template_pwm_step_down_time,
2963 &sensor_dev_template_pwm_start,
2964 &sensor_dev_template_pwm_floor,
2965 &sensor_dev_template_pwm_weight_temp_sel,
2966 &sensor_dev_template_pwm_weight_temp_step,
2967 &sensor_dev_template_pwm_weight_temp_step_tol,
2968 &sensor_dev_template_pwm_weight_temp_step_base,
2969 &sensor_dev_template_pwm_weight_duty_step,
2970 &sensor_dev_template_pwm_max, /* 19 */
2971 &sensor_dev_template_pwm_step, /* 20 */
2972 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2973 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2974 &sensor_dev_template_pwm_auto_point1_temp,
2975 &sensor_dev_template_pwm_auto_point2_pwm,
2976 &sensor_dev_template_pwm_auto_point2_temp,
2977 &sensor_dev_template_pwm_auto_point3_pwm,
2978 &sensor_dev_template_pwm_auto_point3_temp,
2979 &sensor_dev_template_pwm_auto_point4_pwm,
2980 &sensor_dev_template_pwm_auto_point4_temp,
2981 &sensor_dev_template_pwm_auto_point5_pwm,
2982 &sensor_dev_template_pwm_auto_point5_temp,
2983 &sensor_dev_template_pwm_auto_point6_pwm,
2984 &sensor_dev_template_pwm_auto_point6_temp,
2985 &sensor_dev_template_pwm_auto_point7_pwm,
2986 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002987
Guenter Roeckf73cf632013-03-18 09:22:50 -07002988 NULL
2989};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002990
Guenter Roeckf73cf632013-03-18 09:22:50 -07002991static struct sensor_template_group nct6775_pwm_template_group = {
2992 .templates = nct6775_attributes_pwm_template,
2993 .is_visible = nct6775_pwm_is_visible,
2994 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002995};
2996
2997static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002998show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2999{
3000 struct nct6775_data *data = dev_get_drvdata(dev);
3001 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3002}
3003
3004static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3005
Guenter Roecka6bd5872012-12-04 03:13:34 -08003006/* Case open detection */
3007
3008static ssize_t
3009clear_caseopen(struct device *dev, struct device_attribute *attr,
3010 const char *buf, size_t count)
3011{
3012 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003013 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3014 unsigned long val;
3015 u8 reg;
3016 int ret;
3017
3018 if (kstrtoul(buf, 10, &val) || val != 0)
3019 return -EINVAL;
3020
3021 mutex_lock(&data->update_lock);
3022
3023 /*
3024 * Use CR registers to clear caseopen status.
3025 * The CR registers are the same for all chips, and not all chips
3026 * support clearing the caseopen status through "regular" registers.
3027 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003028 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003029 if (ret) {
3030 count = ret;
3031 goto error;
3032 }
3033
Guenter Roeckdf612d52013-07-08 13:15:04 -07003034 superio_select(data->sioreg, NCT6775_LD_ACPI);
3035 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003036 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003037 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003038 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003039 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3040 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003041
3042 data->valid = false; /* Force cache refresh */
3043error:
3044 mutex_unlock(&data->update_lock);
3045 return count;
3046}
3047
Guenter Roeckf73cf632013-03-18 09:22:50 -07003048static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3049 clear_caseopen, INTRUSION_ALARM_BASE);
3050static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3051 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003052static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3053 store_beep, INTRUSION_ALARM_BASE);
3054static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3055 store_beep, INTRUSION_ALARM_BASE + 1);
3056static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3057 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003058
3059static umode_t nct6775_other_is_visible(struct kobject *kobj,
3060 struct attribute *attr, int index)
3061{
3062 struct device *dev = container_of(kobj, struct device, kobj);
3063 struct nct6775_data *data = dev_get_drvdata(dev);
3064
3065 if (index == 1 && !data->have_vid)
3066 return 0;
3067
3068 if (index == 2 || index == 3) {
3069 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
3070 return 0;
3071 }
3072
Guenter Roeck30846992013-06-24 22:21:59 -07003073 if (index == 4 || index == 5) {
3074 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
3075 return 0;
3076 }
3077
Guenter Roeckf73cf632013-03-18 09:22:50 -07003078 return attr->mode;
3079}
3080
3081/*
3082 * nct6775_other_is_visible uses the index into the following array
3083 * to determine if attributes should be created or not.
3084 * Any change in order or content must be matched.
3085 */
3086static struct attribute *nct6775_attributes_other[] = {
3087 &dev_attr_name.attr,
3088 &dev_attr_cpu0_vid.attr, /* 1 */
3089 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
3090 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
Guenter Roeck30846992013-06-24 22:21:59 -07003091 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 4 */
3092 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 5 */
3093 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 6 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003094
3095 NULL
3096};
3097
3098static const struct attribute_group nct6775_group_other = {
3099 .attrs = nct6775_attributes_other,
3100 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003101};
3102
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003103/*
3104 * Driver and device management
3105 */
3106
3107static void nct6775_device_remove_files(struct device *dev)
3108{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003109 struct nct6775_data *data = dev_get_drvdata(dev);
3110
Guenter Roeckf73cf632013-03-18 09:22:50 -07003111 if (data->group_pwm)
3112 sysfs_remove_group(&dev->kobj, data->group_pwm);
3113 if (data->group_in)
3114 sysfs_remove_group(&dev->kobj, data->group_in);
3115 if (data->group_fan)
3116 sysfs_remove_group(&dev->kobj, data->group_fan);
3117 if (data->group_temp)
3118 sysfs_remove_group(&dev->kobj, data->group_temp);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003119
Guenter Roeckf73cf632013-03-18 09:22:50 -07003120 sysfs_remove_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003121}
3122
3123/* Get the monitoring functions started */
3124static inline void nct6775_init_device(struct nct6775_data *data)
3125{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003126 int i;
3127 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003128
3129 /* Start monitoring if needed */
3130 if (data->REG_CONFIG) {
3131 tmp = nct6775_read_value(data, data->REG_CONFIG);
3132 if (!(tmp & 0x01))
3133 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3134 }
3135
Guenter Roeckaa136e52012-12-04 03:26:05 -08003136 /* Enable temperature sensors if needed */
3137 for (i = 0; i < NUM_TEMP; i++) {
3138 if (!(data->have_temp & (1 << i)))
3139 continue;
3140 if (!data->reg_temp_config[i])
3141 continue;
3142 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3143 if (tmp & 0x01)
3144 nct6775_write_value(data, data->reg_temp_config[i],
3145 tmp & 0xfe);
3146 }
3147
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003148 /* Enable VBAT monitoring if needed */
3149 tmp = nct6775_read_value(data, data->REG_VBAT);
3150 if (!(tmp & 0x01))
3151 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003152
3153 diode = nct6775_read_value(data, data->REG_DIODE);
3154
3155 for (i = 0; i < data->temp_fixed_num; i++) {
3156 if (!(data->have_temp_fixed & (1 << i)))
3157 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003158 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3159 data->temp_type[i]
3160 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003161 else /* thermistor */
3162 data->temp_type[i] = 4;
3163 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003164}
3165
Guenter Roeckf73cf632013-03-18 09:22:50 -07003166static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003167nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003168{
David Bartley578ab5f2013-06-24 22:28:28 -07003169 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3170 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003171 int sioreg = data->sioreg;
3172 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003173
3174 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3175 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003176 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003177
3178 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003179 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003180
3181 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003182 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003183 fan4min = false;
3184 fan5pin = false;
3185 fan6pin = false;
3186 pwm4pin = false;
3187 pwm5pin = false;
3188 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003189 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003190 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003191
Guenter Roeckdf612d52013-07-08 13:15:04 -07003192 superio_select(sioreg, NCT6775_LD_HWM);
3193 regval = superio_inb(sioreg, SIO_REG_ENABLE);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003194
3195 if (regval & 0x80)
3196 fan3pin = gpok;
3197 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003198 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003199
3200 if (regval & 0x40)
3201 fan4pin = gpok;
3202 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003203 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003204
3205 if (regval & 0x20)
3206 fan5pin = gpok;
3207 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003208 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003209
3210 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003211 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003212 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003213 pwm4pin = false;
3214 pwm5pin = false;
3215 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003216 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003217 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003218 fan3pin = !(regval & 0x80);
3219 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003220
3221 fan4pin = false;
3222 fan4min = false;
3223 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003224 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003225 pwm4pin = false;
3226 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003227 pwm6pin = false;
3228 } else { /* NCT6779D or NCT6791D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003229 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003230
3231 fan3pin = !(regval & (1 << 5));
3232 fan4pin = !(regval & (1 << 6));
3233 fan5pin = !(regval & (1 << 7));
3234
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003235 pwm3pin = !(regval & (1 << 0));
3236 pwm4pin = !(regval & (1 << 1));
3237 pwm5pin = !(regval & (1 << 2));
3238
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003239 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003240
3241 if (data->kind == nct6791) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003242 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003243 fan6pin = (regval & (1 << 1));
3244 pwm6pin = (regval & (1 << 0));
3245 } else { /* NCT6779D */
3246 fan6pin = false;
3247 pwm6pin = false;
3248 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003249 }
3250
David Bartley578ab5f2013-06-24 22:28:28 -07003251 /* fan 1 and 2 (0x03) are always present */
3252 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3253 (fan5pin << 4) | (fan6pin << 5);
3254 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3255 (fan5pin << 4);
3256 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3257 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003258}
3259
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003260static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3261 int *available, int *mask)
3262{
3263 int i;
3264 u8 src;
3265
3266 for (i = 0; i < data->pwm_num && *available; i++) {
3267 int index;
3268
3269 if (!regp[i])
3270 continue;
3271 src = nct6775_read_value(data, regp[i]);
3272 src &= 0x1f;
3273 if (!src || (*mask & (1 << src)))
3274 continue;
3275 if (src >= data->temp_label_num ||
3276 !strlen(data->temp_label[src]))
3277 continue;
3278
3279 index = __ffs(*available);
3280 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3281 *available &= ~(1 << index);
3282 *mask |= 1 << src;
3283 }
3284}
3285
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003286static int nct6775_probe(struct platform_device *pdev)
3287{
3288 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003289 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003290 struct nct6775_data *data;
3291 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003292 int i, s, err = 0;
3293 int src, mask, available;
3294 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3295 const u16 *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003296 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003297 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003298 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003299 struct attribute_group *group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003300
3301 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3302 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3303 DRVNAME))
3304 return -EBUSY;
3305
3306 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3307 GFP_KERNEL);
3308 if (!data)
3309 return -ENOMEM;
3310
3311 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003312 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003313 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003314 mutex_init(&data->update_lock);
3315 data->name = nct6775_device_names[data->kind];
3316 data->bank = 0xff; /* Force initial bank selection */
3317 platform_set_drvdata(pdev, data);
3318
3319 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003320 case nct6106:
3321 data->in_num = 9;
3322 data->pwm_num = 3;
3323 data->auto_pwm_num = 4;
3324 data->temp_fixed_num = 3;
3325 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003326 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003327
3328 data->fan_from_reg = fan_from_reg13;
3329 data->fan_from_reg_min = fan_from_reg13;
3330
3331 data->temp_label = nct6776_temp_label;
3332 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3333
3334 data->REG_VBAT = NCT6106_REG_VBAT;
3335 data->REG_DIODE = NCT6106_REG_DIODE;
3336 data->DIODE_MASK = NCT6106_DIODE_MASK;
3337 data->REG_VIN = NCT6106_REG_IN;
3338 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3339 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3340 data->REG_TARGET = NCT6106_REG_TARGET;
3341 data->REG_FAN = NCT6106_REG_FAN;
3342 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3343 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3344 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3345 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3346 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3347 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3348 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3349 data->REG_PWM[0] = NCT6106_REG_PWM;
3350 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3351 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3352 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3353 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3354 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3355 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3356 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3357 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3358 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3359 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3360 data->REG_CRITICAL_TEMP_TOLERANCE
3361 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3362 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3363 data->CRITICAL_PWM_ENABLE_MASK
3364 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3365 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3366 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3367 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3368 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3369 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3370 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3371 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3372 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3373 data->REG_ALARM = NCT6106_REG_ALARM;
3374 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003375 data->REG_BEEP = NCT6106_REG_BEEP;
3376 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003377
3378 reg_temp = NCT6106_REG_TEMP;
3379 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3380 reg_temp_over = NCT6106_REG_TEMP_OVER;
3381 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3382 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3383 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3384 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003385 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3386 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003387
3388 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003389 case nct6775:
3390 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003391 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003392 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003393 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003394 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003395 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003396 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003397
3398 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003399 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003400
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003401 data->fan_from_reg = fan_from_reg16;
3402 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003403 data->target_temp_mask = 0x7f;
3404 data->tolerance_mask = 0x0f;
3405 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003406
Guenter Roeckaa136e52012-12-04 03:26:05 -08003407 data->temp_label = nct6775_temp_label;
3408 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3409
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003410 data->REG_CONFIG = NCT6775_REG_CONFIG;
3411 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003412 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003413 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003414 data->REG_VIN = NCT6775_REG_IN;
3415 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3416 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003417 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003418 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003419 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003420 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003421 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003422 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003423 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3424 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3425 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003426 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003427 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3428 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3429 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3430 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003431 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003432 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3433 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3434 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003435 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3436 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3437 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3438 data->REG_CRITICAL_TEMP_TOLERANCE
3439 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003440 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3441 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003442 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003443 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3444 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3445 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3446 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003447 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003448 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003449
3450 reg_temp = NCT6775_REG_TEMP;
3451 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3452 reg_temp_over = NCT6775_REG_TEMP_OVER;
3453 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3454 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3455 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3456 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3457
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003458 break;
3459 case nct6776:
3460 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003461 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003462 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003463 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003464 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003465 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003466 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003467
3468 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003469 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003470
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003471 data->fan_from_reg = fan_from_reg13;
3472 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003473 data->target_temp_mask = 0xff;
3474 data->tolerance_mask = 0x07;
3475 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003476
Guenter Roeckaa136e52012-12-04 03:26:05 -08003477 data->temp_label = nct6776_temp_label;
3478 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3479
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003480 data->REG_CONFIG = NCT6775_REG_CONFIG;
3481 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003482 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003483 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003484 data->REG_VIN = NCT6775_REG_IN;
3485 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3486 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003487 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003488 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003489 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003490 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003491 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003492 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003493 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3494 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3495 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3496 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003497 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003498 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3499 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003500 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3501 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003502 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3503 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3504 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003505 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3506 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3507 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3508 data->REG_CRITICAL_TEMP_TOLERANCE
3509 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003510 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3511 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003512 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003513 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3514 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3515 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3516 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003517 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003518 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003519
3520 reg_temp = NCT6775_REG_TEMP;
3521 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3522 reg_temp_over = NCT6775_REG_TEMP_OVER;
3523 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3524 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3525 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3526 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3527
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003528 break;
3529 case nct6779:
3530 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003531 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003532 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003533 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003534 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003535 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003536 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003537
3538 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003539 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003540
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003541 data->fan_from_reg = fan_from_reg13;
3542 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003543 data->target_temp_mask = 0xff;
3544 data->tolerance_mask = 0x07;
3545 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003546
Guenter Roeckaa136e52012-12-04 03:26:05 -08003547 data->temp_label = nct6779_temp_label;
3548 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3549
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003550 data->REG_CONFIG = NCT6775_REG_CONFIG;
3551 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003552 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003553 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003554 data->REG_VIN = NCT6779_REG_IN;
3555 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3556 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003557 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003558 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003559 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003560 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003561 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003562 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003563 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3564 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3565 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3566 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003567 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003568 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3569 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003570 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3571 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003572 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3573 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3574 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003575 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3576 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3577 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3578 data->REG_CRITICAL_TEMP_TOLERANCE
3579 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003580 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3581 data->CRITICAL_PWM_ENABLE_MASK
3582 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3583 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003584 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3585 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003586 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003587 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3588 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3589 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3590 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003591 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003592 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003593
3594 reg_temp = NCT6779_REG_TEMP;
3595 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3596 reg_temp_over = NCT6779_REG_TEMP_OVER;
3597 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3598 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3599 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3600 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3601
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003602 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003603 case nct6791:
3604 data->in_num = 15;
3605 data->pwm_num = 6;
3606 data->auto_pwm_num = 4;
3607 data->has_fan_div = false;
3608 data->temp_fixed_num = 6;
3609 data->num_temp_alarms = 2;
3610 data->num_temp_beeps = 2;
3611
3612 data->ALARM_BITS = NCT6791_ALARM_BITS;
3613 data->BEEP_BITS = NCT6779_BEEP_BITS;
3614
3615 data->fan_from_reg = fan_from_reg13;
3616 data->fan_from_reg_min = fan_from_reg13;
3617 data->target_temp_mask = 0xff;
3618 data->tolerance_mask = 0x07;
3619 data->speed_tolerance_limit = 63;
3620
3621 data->temp_label = nct6779_temp_label;
3622 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3623
3624 data->REG_CONFIG = NCT6775_REG_CONFIG;
3625 data->REG_VBAT = NCT6775_REG_VBAT;
3626 data->REG_DIODE = NCT6775_REG_DIODE;
3627 data->DIODE_MASK = NCT6775_DIODE_MASK;
3628 data->REG_VIN = NCT6779_REG_IN;
3629 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3630 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3631 data->REG_TARGET = NCT6775_REG_TARGET;
3632 data->REG_FAN = NCT6779_REG_FAN;
3633 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3634 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3635 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3636 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3637 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3638 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3639 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3640 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3641 data->REG_PWM[0] = NCT6775_REG_PWM;
3642 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3643 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3644 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3645 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3646 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3647 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3648 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3649 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3650 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3651 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3652 data->REG_CRITICAL_TEMP_TOLERANCE
3653 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3654 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3655 data->CRITICAL_PWM_ENABLE_MASK
3656 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3657 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3658 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3659 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3660 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3661 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3662 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3663 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3664 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3665 data->REG_ALARM = NCT6791_REG_ALARM;
3666 data->REG_BEEP = NCT6776_REG_BEEP;
3667
3668 reg_temp = NCT6779_REG_TEMP;
3669 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3670 reg_temp_over = NCT6779_REG_TEMP_OVER;
3671 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3672 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3673 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3674 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3675
3676 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003677 default:
3678 return -ENODEV;
3679 }
3680 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003681 data->have_temp = 0;
3682
3683 /*
3684 * On some boards, not all available temperature sources are monitored,
3685 * even though some of the monitoring registers are unused.
3686 * Get list of unused monitoring registers, then detect if any fan
3687 * controls are configured to use unmonitored temperature sources.
3688 * If so, assign the unmonitored temperature sources to available
3689 * monitoring registers.
3690 */
3691 mask = 0;
3692 available = 0;
3693 for (i = 0; i < num_reg_temp; i++) {
3694 if (reg_temp[i] == 0)
3695 continue;
3696
3697 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3698 if (!src || (mask & (1 << src)))
3699 available |= 1 << i;
3700
3701 mask |= 1 << src;
3702 }
3703
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003704 /*
3705 * Now find unmonitored temperature registers and enable monitoring
3706 * if additional monitoring registers are available.
3707 */
3708 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3709 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3710
Guenter Roeckaa136e52012-12-04 03:26:05 -08003711 mask = 0;
3712 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3713 for (i = 0; i < num_reg_temp; i++) {
3714 if (reg_temp[i] == 0)
3715 continue;
3716
3717 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3718 if (!src || (mask & (1 << src)))
3719 continue;
3720
3721 if (src >= data->temp_label_num ||
3722 !strlen(data->temp_label[src])) {
3723 dev_info(dev,
3724 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3725 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3726 continue;
3727 }
3728
3729 mask |= 1 << src;
3730
3731 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3732 if (src <= data->temp_fixed_num) {
3733 data->have_temp |= 1 << (src - 1);
3734 data->have_temp_fixed |= 1 << (src - 1);
3735 data->reg_temp[0][src - 1] = reg_temp[i];
3736 data->reg_temp[1][src - 1] = reg_temp_over[i];
3737 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003738 if (reg_temp_crit_h && reg_temp_crit_h[i])
3739 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3740 else if (reg_temp_crit[src - 1])
3741 data->reg_temp[3][src - 1]
3742 = reg_temp_crit[src - 1];
3743 if (reg_temp_crit_l && reg_temp_crit_l[i])
3744 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003745 data->reg_temp_config[src - 1] = reg_temp_config[i];
3746 data->temp_src[src - 1] = src;
3747 continue;
3748 }
3749
3750 if (s >= NUM_TEMP)
3751 continue;
3752
3753 /* Use dynamic index for other sources */
3754 data->have_temp |= 1 << s;
3755 data->reg_temp[0][s] = reg_temp[i];
3756 data->reg_temp[1][s] = reg_temp_over[i];
3757 data->reg_temp[2][s] = reg_temp_hyst[i];
3758 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003759 if (reg_temp_crit_h && reg_temp_crit_h[i])
3760 data->reg_temp[3][s] = reg_temp_crit_h[i];
3761 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003762 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003763 if (reg_temp_crit_l && reg_temp_crit_l[i])
3764 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003765
3766 data->temp_src[s] = src;
3767 s++;
3768 }
3769
3770#ifdef USE_ALTERNATE
3771 /*
3772 * Go through the list of alternate temp registers and enable
3773 * if possible.
3774 * The temperature is already monitored if the respective bit in <mask>
3775 * is set.
3776 */
3777 for (i = 0; i < data->temp_label_num - 1; i++) {
3778 if (!reg_temp_alternate[i])
3779 continue;
3780 if (mask & (1 << (i + 1)))
3781 continue;
3782 if (i < data->temp_fixed_num) {
3783 if (data->have_temp & (1 << i))
3784 continue;
3785 data->have_temp |= 1 << i;
3786 data->have_temp_fixed |= 1 << i;
3787 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003788 if (i < num_reg_temp) {
3789 data->reg_temp[1][i] = reg_temp_over[i];
3790 data->reg_temp[2][i] = reg_temp_hyst[i];
3791 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003792 data->temp_src[i] = i + 1;
3793 continue;
3794 }
3795
3796 if (s >= NUM_TEMP) /* Abort if no more space */
3797 break;
3798
3799 data->have_temp |= 1 << s;
3800 data->reg_temp[0][s] = reg_temp_alternate[i];
3801 data->temp_src[s] = i + 1;
3802 s++;
3803 }
3804#endif /* USE_ALTERNATE */
3805
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003806 /* Initialize the chip */
3807 nct6775_init_device(data);
3808
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003809 err = superio_enter(sio_data->sioreg);
3810 if (err)
3811 return err;
3812
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003813 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3814 switch (data->kind) {
3815 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003816 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003817 break;
3818 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003819 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003820 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003821 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003822 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003823 case nct6791:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003824 break;
3825 }
3826
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003827 /*
3828 * Read VID value
3829 * We can get the VID input values directly at logical device D 0xe3.
3830 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003831 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003832 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3833 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3834 data->vrm = vid_which_vrm();
3835 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003836
3837 if (fan_debounce) {
3838 u8 tmp;
3839
3840 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3841 tmp = superio_inb(sio_data->sioreg,
3842 NCT6775_REG_CR_FAN_DEBOUNCE);
3843 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003844 case nct6106:
3845 tmp |= 0xe0;
3846 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003847 case nct6775:
3848 tmp |= 0x1e;
3849 break;
3850 case nct6776:
3851 case nct6779:
3852 tmp |= 0x3e;
3853 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003854 case nct6791:
3855 tmp |= 0x7e;
3856 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003857 }
3858 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3859 tmp);
3860 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3861 data->name);
3862 }
3863
Guenter Roeckdf612d52013-07-08 13:15:04 -07003864 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003865
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003866 superio_exit(sio_data->sioreg);
3867
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003868 /* Read fan clock dividers immediately */
3869 nct6775_init_fan_common(dev, data);
3870
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003871 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003872 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3873 data->pwm_num);
3874 if (IS_ERR(group)) {
3875 err = PTR_ERR(group);
3876 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003877 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003878 data->group_pwm = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003879
Guenter Roeckf73cf632013-03-18 09:22:50 -07003880 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3881 fls(data->have_in));
3882 if (IS_ERR(group)) {
3883 err = PTR_ERR(group);
3884 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003885 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003886 data->group_in = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003887
Guenter Roeckf73cf632013-03-18 09:22:50 -07003888 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3889 fls(data->has_fan));
3890 if (IS_ERR(group)) {
3891 err = PTR_ERR(group);
3892 goto exit_remove;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003893 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003894 data->group_fan = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003895
Guenter Roeckf73cf632013-03-18 09:22:50 -07003896 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3897 fls(data->have_temp));
3898 if (IS_ERR(group)) {
3899 err = PTR_ERR(group);
3900 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003901 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003902 data->group_temp = group;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003903
Guenter Roeckf73cf632013-03-18 09:22:50 -07003904 err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003905 if (err)
3906 goto exit_remove;
3907
3908 data->hwmon_dev = hwmon_device_register(dev);
3909 if (IS_ERR(data->hwmon_dev)) {
3910 err = PTR_ERR(data->hwmon_dev);
3911 goto exit_remove;
3912 }
3913
3914 return 0;
3915
3916exit_remove:
3917 nct6775_device_remove_files(dev);
3918 return err;
3919}
3920
3921static int nct6775_remove(struct platform_device *pdev)
3922{
3923 struct nct6775_data *data = platform_get_drvdata(pdev);
3924
3925 hwmon_device_unregister(data->hwmon_dev);
3926 nct6775_device_remove_files(&pdev->dev);
3927
3928 return 0;
3929}
3930
Guenter Roeck84d19d92012-12-04 08:01:39 -08003931#ifdef CONFIG_PM
3932static int nct6775_suspend(struct device *dev)
3933{
3934 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003935
3936 mutex_lock(&data->update_lock);
3937 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003938 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003939 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3940 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3941 }
3942 mutex_unlock(&data->update_lock);
3943
3944 return 0;
3945}
3946
3947static int nct6775_resume(struct device *dev)
3948{
3949 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003950 int i, j;
3951
3952 mutex_lock(&data->update_lock);
3953 data->bank = 0xff; /* Force initial bank selection */
3954
3955 /* Restore limits */
3956 for (i = 0; i < data->in_num; i++) {
3957 if (!(data->have_in & (1 << i)))
3958 continue;
3959
3960 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3961 data->in[i][1]);
3962 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3963 data->in[i][2]);
3964 }
3965
Guenter Roeckc409fd42013-04-09 05:04:00 -07003966 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003967 if (!(data->has_fan_min & (1 << i)))
3968 continue;
3969
3970 nct6775_write_value(data, data->REG_FAN_MIN[i],
3971 data->fan_min[i]);
3972 }
3973
3974 for (i = 0; i < NUM_TEMP; i++) {
3975 if (!(data->have_temp & (1 << i)))
3976 continue;
3977
Guenter Roeckc409fd42013-04-09 05:04:00 -07003978 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003979 if (data->reg_temp[j][i])
3980 nct6775_write_temp(data, data->reg_temp[j][i],
3981 data->temp[j][i]);
3982 }
3983
3984 /* Restore other settings */
3985 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003986 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003987 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3988 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3989 }
3990
3991 /* Force re-reading all values */
3992 data->valid = false;
3993 mutex_unlock(&data->update_lock);
3994
3995 return 0;
3996}
3997
3998static const struct dev_pm_ops nct6775_dev_pm_ops = {
3999 .suspend = nct6775_suspend,
4000 .resume = nct6775_resume,
Harald Judt374d1f92013-07-30 19:50:16 +02004001 .freeze = nct6775_suspend,
4002 .restore = nct6775_resume,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004003};
4004
4005#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4006#else
4007#define NCT6775_DEV_PM_OPS NULL
4008#endif /* CONFIG_PM */
4009
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004010static struct platform_driver nct6775_driver = {
4011 .driver = {
4012 .owner = THIS_MODULE,
4013 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004014 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004015 },
4016 .probe = nct6775_probe,
4017 .remove = nct6775_remove,
4018};
4019
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004020static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07004021 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004022 "NCT6775F",
4023 "NCT6776D/F",
4024 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07004025 "NCT6791D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004026};
4027
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004028/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004029static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004030{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004031 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004032 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004033 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004034
4035 err = superio_enter(sioaddr);
4036 if (err)
4037 return err;
4038
4039 if (force_id)
4040 val = force_id;
4041 else
4042 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4043 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4044 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07004045 case SIO_NCT6106_ID:
4046 sio_data->kind = nct6106;
4047 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004048 case SIO_NCT6775_ID:
4049 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004050 break;
4051 case SIO_NCT6776_ID:
4052 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004053 break;
4054 case SIO_NCT6779_ID:
4055 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004056 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004057 case SIO_NCT6791_ID:
4058 sio_data->kind = nct6791;
4059 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004060 default:
4061 if (val != 0xffff)
4062 pr_debug("unsupported chip ID: 0x%04x\n", val);
4063 superio_exit(sioaddr);
4064 return -ENODEV;
4065 }
4066
4067 /* We have a known chip, find the HWM I/O address */
4068 superio_select(sioaddr, NCT6775_LD_HWM);
4069 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4070 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004071 addr = val & IOREGION_ALIGNMENT;
4072 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004073 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4074 superio_exit(sioaddr);
4075 return -ENODEV;
4076 }
4077
4078 /* Activate logical device if needed */
4079 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4080 if (!(val & 0x01)) {
4081 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4082 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4083 }
David Bartley578ab5f2013-06-24 22:28:28 -07004084 if (sio_data->kind == nct6791) {
4085 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
4086 if (val & 0x10) {
4087 pr_info("Enabling hardware monitor logical device mappings.\n");
4088 superio_outb(sioaddr,
4089 NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
4090 val & ~0x10);
4091 }
4092 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004093
4094 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004095 pr_info("Found %s or compatible chip at %#x:%#x\n",
4096 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004097 sio_data->sioreg = sioaddr;
4098
Guenter Roeck698a7c22013-04-05 07:35:25 -07004099 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004100}
4101
4102/*
4103 * when Super-I/O functions move to a separate file, the Super-I/O
4104 * bus will manage the lifetime of the device and this module will only keep
4105 * track of the nct6775 driver. But since we platform_device_alloc(), we
4106 * must keep track of the device
4107 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004108static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004109
4110static int __init sensors_nct6775_init(void)
4111{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004112 int i, err;
4113 bool found = false;
4114 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004115 struct resource res;
4116 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004117 int sioaddr[2] = { 0x2e, 0x4e };
4118
4119 err = platform_driver_register(&nct6775_driver);
4120 if (err)
4121 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004122
4123 /*
4124 * initialize sio_data->kind and sio_data->sioreg.
4125 *
4126 * when Super-I/O functions move to a separate file, the Super-I/O
4127 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4128 * nct6775 hardware monitor, and call probe()
4129 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004130 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4131 address = nct6775_find(sioaddr[i], &sio_data);
4132 if (address <= 0)
4133 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004134
Guenter Roeck698a7c22013-04-05 07:35:25 -07004135 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004136
Guenter Roeck698a7c22013-04-05 07:35:25 -07004137 pdev[i] = platform_device_alloc(DRVNAME, address);
4138 if (!pdev[i]) {
4139 err = -ENOMEM;
4140 goto exit_device_put;
4141 }
4142
4143 err = platform_device_add_data(pdev[i], &sio_data,
4144 sizeof(struct nct6775_sio_data));
4145 if (err)
4146 goto exit_device_put;
4147
4148 memset(&res, 0, sizeof(res));
4149 res.name = DRVNAME;
4150 res.start = address + IOREGION_OFFSET;
4151 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4152 res.flags = IORESOURCE_IO;
4153
4154 err = acpi_check_resource_conflict(&res);
4155 if (err) {
4156 platform_device_put(pdev[i]);
4157 pdev[i] = NULL;
4158 continue;
4159 }
4160
4161 err = platform_device_add_resources(pdev[i], &res, 1);
4162 if (err)
4163 goto exit_device_put;
4164
4165 /* platform_device_add calls probe() */
4166 err = platform_device_add(pdev[i]);
4167 if (err)
4168 goto exit_device_put;
4169 }
4170 if (!found) {
4171 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004172 goto exit_unregister;
4173 }
4174
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004175 return 0;
4176
4177exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07004178 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4179 if (pdev[i])
4180 platform_device_put(pdev[i]);
4181 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004182exit_unregister:
4183 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004184 return err;
4185}
4186
4187static void __exit sensors_nct6775_exit(void)
4188{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004189 int i;
4190
4191 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4192 if (pdev[i])
4193 platform_device_unregister(pdev[i]);
4194 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004195 platform_driver_unregister(&nct6775_driver);
4196}
4197
4198MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4199MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4200MODULE_LICENSE("GPL");
4201
4202module_init(sensors_nct6775_init);
4203module_exit(sensors_nct6775_exit);