blob: 3f4ef21010d5b6fb6152e6a30152fac74aaf43de [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
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800277static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77 };
278
Guenter Roeckaa136e52012-12-04 03:26:05 -0800279static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
280 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
281static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
282 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
283static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
284 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
285
286static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
287 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
288
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800289static const u16 NCT6775_REG_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700290 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800291
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800292static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700293 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800294static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700295 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800296static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700297 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800298static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700299 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800300static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700301 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800302
Guenter Roeckaa136e52012-12-04 03:26:05 -0800303static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
304
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800305static const u16 NCT6775_REG_AUTO_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700306 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800307static const u16 NCT6775_REG_AUTO_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700308 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800309
310#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
311#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
312
313static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
314
315static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700316 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800317static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700318 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800319
Guenter Roeckaa136e52012-12-04 03:26:05 -0800320static const char *const nct6775_temp_label[] = {
321 "",
322 "SYSTIN",
323 "CPUTIN",
324 "AUXTIN",
325 "AMD SB-TSI",
326 "PECI Agent 0",
327 "PECI Agent 1",
328 "PECI Agent 2",
329 "PECI Agent 3",
330 "PECI Agent 4",
331 "PECI Agent 5",
332 "PECI Agent 6",
333 "PECI Agent 7",
334 "PCH_CHIP_CPU_MAX_TEMP",
335 "PCH_CHIP_TEMP",
336 "PCH_CPU_TEMP",
337 "PCH_MCH_TEMP",
338 "PCH_DIM0_TEMP",
339 "PCH_DIM1_TEMP",
340 "PCH_DIM2_TEMP",
341 "PCH_DIM3_TEMP"
342};
343
344static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
345 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
346
347static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
348 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
349 0xa07 };
350
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700351/* NCT6776 specific data */
352
353static const s8 NCT6776_ALARM_BITS[] = {
354 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
355 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
356 -1, /* unused */
357 6, 7, 11, 10, 23, /* fan1..fan5 */
358 -1, -1, -1, /* unused */
359 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
360 12, 9 }; /* intrusion0, intrusion1 */
361
Guenter Roeck30846992013-06-24 22:21:59 -0700362static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
363
364static const s8 NCT6776_BEEP_BITS[] = {
365 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
366 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
367 24, /* global beep enable */
368 25, 26, 27, 28, 29, /* fan1..fan5 */
369 -1, -1, -1, /* unused */
370 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
371 30, 31 }; /* intrusion0, intrusion1 */
372
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800373static const u16 NCT6776_REG_TOLERANCE_H[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700374 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800375
David Bartley578ab5f2013-06-24 22:28:28 -0700376static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
377static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800378
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800379static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800380static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800381
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800382static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700383 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800384
Guenter Roeckaa136e52012-12-04 03:26:05 -0800385static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
386 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
387
388static const char *const nct6776_temp_label[] = {
389 "",
390 "SYSTIN",
391 "CPUTIN",
392 "AUXTIN",
393 "SMBUSMASTER 0",
394 "SMBUSMASTER 1",
395 "SMBUSMASTER 2",
396 "SMBUSMASTER 3",
397 "SMBUSMASTER 4",
398 "SMBUSMASTER 5",
399 "SMBUSMASTER 6",
400 "SMBUSMASTER 7",
401 "PECI Agent 0",
402 "PECI Agent 1",
403 "PCH_CHIP_CPU_MAX_TEMP",
404 "PCH_CHIP_TEMP",
405 "PCH_CPU_TEMP",
406 "PCH_MCH_TEMP",
407 "PCH_DIM0_TEMP",
408 "PCH_DIM1_TEMP",
409 "PCH_DIM2_TEMP",
410 "PCH_DIM3_TEMP",
411 "BYTE_TEMP"
412};
413
414static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
415 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
416
417static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
418 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
419
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700420/* NCT6779 specific data */
421
422static const u16 NCT6779_REG_IN[] = {
423 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
424 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
425
426static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
427 0x459, 0x45A, 0x45B, 0x568 };
428
429static const s8 NCT6779_ALARM_BITS[] = {
430 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
431 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
432 -1, /* unused */
433 6, 7, 11, 10, 23, /* fan1..fan5 */
434 -1, -1, -1, /* unused */
435 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
436 12, 9 }; /* intrusion0, intrusion1 */
437
Guenter Roeck30846992013-06-24 22:21:59 -0700438static const s8 NCT6779_BEEP_BITS[] = {
439 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
440 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
441 24, /* global beep enable */
442 25, 26, 27, 28, 29, /* fan1..fan5 */
443 -1, -1, -1, /* unused */
444 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
445 30, 31 }; /* intrusion0, intrusion1 */
446
David Bartley578ab5f2013-06-24 22:28:28 -0700447static const u16 NCT6779_REG_FAN[] = {
448 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800449static const u16 NCT6779_REG_FAN_PULSES[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700450 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800451
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800452static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700453 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700454#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800455static const u16 NCT6779_REG_CRITICAL_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700456 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800457
Guenter Roeckaa136e52012-12-04 03:26:05 -0800458static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800459static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
Guenter Roeckaa136e52012-12-04 03:26:05 -0800460static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
461 0x18, 0x152 };
462static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
463 0x3a, 0x153 };
464static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
465 0x39, 0x155 };
466
467static const u16 NCT6779_REG_TEMP_OFFSET[] = {
468 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
469
470static const char *const nct6779_temp_label[] = {
471 "",
472 "SYSTIN",
473 "CPUTIN",
474 "AUXTIN0",
475 "AUXTIN1",
476 "AUXTIN2",
477 "AUXTIN3",
478 "",
479 "SMBUSMASTER 0",
480 "SMBUSMASTER 1",
481 "SMBUSMASTER 2",
482 "SMBUSMASTER 3",
483 "SMBUSMASTER 4",
484 "SMBUSMASTER 5",
485 "SMBUSMASTER 6",
486 "SMBUSMASTER 7",
487 "PECI Agent 0",
488 "PECI Agent 1",
489 "PCH_CHIP_CPU_MAX_TEMP",
490 "PCH_CHIP_TEMP",
491 "PCH_CPU_TEMP",
492 "PCH_MCH_TEMP",
493 "PCH_DIM0_TEMP",
494 "PCH_DIM1_TEMP",
495 "PCH_DIM2_TEMP",
496 "PCH_DIM3_TEMP",
497 "BYTE_TEMP"
498};
499
500static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
501 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
502 0, 0, 0, 0, 0, 0, 0, 0,
503 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
504 0x408, 0 };
505
506static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
507 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
508
David Bartley578ab5f2013-06-24 22:28:28 -0700509/* NCT6791 specific data */
510
511#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
512
513static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
514 0x459, 0x45A, 0x45B, 0x568, 0x45D };
515
516static const s8 NCT6791_ALARM_BITS[] = {
517 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
518 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
519 -1, /* unused */
520 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
521 -1, -1, /* unused */
522 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
523 12, 9 }; /* intrusion0, intrusion1 */
524
525
Guenter Roeck6c009502012-07-01 08:23:15 -0700526/* NCT6102D/NCT6106D specific data */
527
528#define NCT6106_REG_VBAT 0x318
529#define NCT6106_REG_DIODE 0x319
530#define NCT6106_DIODE_MASK 0x01
531
532static const u16 NCT6106_REG_IN_MAX[] = {
533 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
534static const u16 NCT6106_REG_IN_MIN[] = {
535 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
536static const u16 NCT6106_REG_IN[] = {
537 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
538
539static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800540static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
Guenter Roeck6c009502012-07-01 08:23:15 -0700541static const u16 NCT6106_REG_TEMP_HYST[] = {
542 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
543static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700544 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
545static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
546 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
547static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
548 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700549static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
550static const u16 NCT6106_REG_TEMP_CONFIG[] = {
551 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
552
553static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
554static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
555static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
556static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
557
558static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
559static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
560static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
561static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
562static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
563static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
564static const u16 NCT6106_REG_TEMP_SOURCE[] = {
565 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
566
567static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
568static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
569 0x11b, 0x12b, 0x13b };
570
571static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
572#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
573static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
574
575static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
576static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
577static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
578static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
579static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
580static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
581
582static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
583
584static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
585static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
586static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
587static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
588static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
589static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
590
591static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
592static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
593
594static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
595 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
596
597static const s8 NCT6106_ALARM_BITS[] = {
598 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
599 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
600 -1, /* unused */
601 32, 33, 34, -1, -1, /* fan1..fan5 */
602 -1, -1, -1, /* unused */
603 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
604 48, -1 /* intrusion0, intrusion1 */
605};
606
Guenter Roeck30846992013-06-24 22:21:59 -0700607static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
608 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
609
610static const s8 NCT6106_BEEP_BITS[] = {
611 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
612 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
613 32, /* global beep enable */
614 24, 25, 26, 27, 28, /* fan1..fan5 */
615 -1, -1, -1, /* unused */
616 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
617 34, -1 /* intrusion0, intrusion1 */
618};
619
Guenter Roeck6c009502012-07-01 08:23:15 -0700620static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
621 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
622
623static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
624 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
625
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800626static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
627{
628 if (mode == 0 && pwm == 255)
629 return off;
630 return mode + 1;
631}
632
633static int pwm_enable_to_reg(enum pwm_enable mode)
634{
635 if (mode == off)
636 return 0;
637 return mode - 1;
638}
639
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700640/*
641 * Conversions
642 */
643
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800644/* 1 is DC mode, output in ms */
645static unsigned int step_time_from_reg(u8 reg, u8 mode)
646{
647 return mode ? 400 * reg : 100 * reg;
648}
649
650static u8 step_time_to_reg(unsigned int msec, u8 mode)
651{
652 return clamp_val((mode ? (msec + 200) / 400 :
653 (msec + 50) / 100), 1, 255);
654}
655
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800656static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
657{
658 if (reg == 0 || reg == 255)
659 return 0;
660 return 1350000U / (reg << divreg);
661}
662
663static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
664{
665 if ((reg & 0xff1f) == 0xff1f)
666 return 0;
667
668 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
669
670 if (reg == 0)
671 return 0;
672
673 return 1350000U / reg;
674}
675
676static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
677{
678 if (reg == 0 || reg == 0xffff)
679 return 0;
680
681 /*
682 * Even though the registers are 16 bit wide, the fan divisor
683 * still applies.
684 */
685 return 1350000U / (reg << divreg);
686}
687
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800688static u16 fan_to_reg(u32 fan, unsigned int divreg)
689{
690 if (!fan)
691 return 0;
692
693 return (1350000U / fan) >> divreg;
694}
695
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800696static inline unsigned int
697div_from_reg(u8 reg)
698{
699 return 1 << reg;
700}
701
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700702/*
703 * Some of the voltage inputs have internal scaling, the tables below
704 * contain 8 (the ADC LSB in mV) * scaling factor * 100
705 */
706static const u16 scale_in[15] = {
707 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
708 800, 800
709};
710
711static inline long in_from_reg(u8 reg, u8 nr)
712{
713 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
714}
715
716static inline u8 in_to_reg(u32 val, u8 nr)
717{
718 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
719}
720
721/*
722 * Data structures and manipulation thereof
723 */
724
725struct nct6775_data {
726 int addr; /* IO base of hw monitor block */
Guenter Roeckdf612d52013-07-08 13:15:04 -0700727 int sioreg; /* SIO register address */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700728 enum kinds kind;
729 const char *name;
730
Guenter Roeck615fc8c2013-07-06 09:43:30 -0700731 int num_attr_groups;
732 const struct attribute_group *groups[6];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700733
Guenter Roeckb7a61352013-04-02 22:14:06 -0700734 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
735 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800736 */
737 u8 temp_src[NUM_TEMP];
738 u16 reg_temp_config[NUM_TEMP];
739 const char * const *temp_label;
740 int temp_label_num;
741
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700742 u16 REG_CONFIG;
743 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800744 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700745 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700746
747 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700748 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700749
750 const u16 *REG_VIN;
751 const u16 *REG_IN_MINMAX[2];
752
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800753 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800754 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800755 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800756 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800757 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700758 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800759 const u16 *REG_FAN_TIME[3];
760
761 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800762
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800763 const u8 *REG_PWM_MODE;
764 const u8 *PWM_MODE_MASK;
765
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800766 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
767 * [3]=pwm_max, [4]=pwm_step,
768 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800769 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800770 const u16 *REG_PWM_READ;
771
Guenter Roeck6c009502012-07-01 08:23:15 -0700772 const u16 *REG_CRITICAL_PWM_ENABLE;
773 u8 CRITICAL_PWM_ENABLE_MASK;
774 const u16 *REG_CRITICAL_PWM;
775
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800776 const u16 *REG_AUTO_TEMP;
777 const u16 *REG_AUTO_PWM;
778
779 const u16 *REG_CRITICAL_TEMP;
780 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
781
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800782 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800783 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800784 const u16 *REG_WEIGHT_TEMP_SEL;
785 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
786
Guenter Roeckaa136e52012-12-04 03:26:05 -0800787 const u16 *REG_TEMP_OFFSET;
788
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700789 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700790 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700791
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800792 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
793 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
794
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700795 struct mutex update_lock;
796 bool valid; /* true if following fields are valid */
797 unsigned long last_updated; /* In jiffies */
798
799 /* Register values */
800 u8 bank; /* current register bank */
801 u8 in_num; /* number of in inputs we have */
802 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
David Bartley578ab5f2013-06-24 22:28:28 -0700803 unsigned int rpm[NUM_FAN];
804 u16 fan_min[NUM_FAN];
805 u8 fan_pulses[NUM_FAN];
806 u8 fan_div[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800807 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800808 u8 has_fan; /* some fan inputs can be disabled */
809 u8 has_fan_min; /* some fans don't have min register */
810 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700811
Guenter Roeck6c009502012-07-01 08:23:15 -0700812 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700813 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800814 u8 temp_fixed_num; /* 3 or 6 */
815 u8 temp_type[NUM_TEMP_FIXED];
816 s8 temp_offset[NUM_TEMP_FIXED];
Dan Carpenterf58876a2013-07-18 18:01:11 +0300817 s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
818 * 3=temp_crit, 4=temp_lcrit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700819 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700820 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700821
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800822 u8 pwm_num; /* number of pwm */
David Bartley578ab5f2013-06-24 22:28:28 -0700823 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
824 * 0->PWM variable duty cycle
825 */
826 enum pwm_enable pwm_enable[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800827 /* 0->off
828 * 1->manual
829 * 2->thermal cruise mode (also called SmartFan I)
830 * 3->fan speed cruise mode
831 * 4->SmartFan III
832 * 5->enhanced variable thermal cruise (SmartFan IV)
833 */
David Bartley578ab5f2013-06-24 22:28:28 -0700834 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
835 * [3]=pwm_max, [4]=pwm_step,
836 * [5]=weight_duty_step, [6]=weight_duty_base
837 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800838
David Bartley578ab5f2013-06-24 22:28:28 -0700839 u8 target_temp[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800840 u8 target_temp_mask;
David Bartley578ab5f2013-06-24 22:28:28 -0700841 u32 target_speed[NUM_FAN];
842 u32 target_speed_tolerance[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800843 u8 speed_tolerance_limit;
844
David Bartley578ab5f2013-06-24 22:28:28 -0700845 u8 temp_tolerance[2][NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800846 u8 tolerance_mask;
847
David Bartley578ab5f2013-06-24 22:28:28 -0700848 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800849
850 /* Automatic fan speed control registers */
851 int auto_pwm_num;
David Bartley578ab5f2013-06-24 22:28:28 -0700852 u8 auto_pwm[NUM_FAN][7];
853 u8 auto_temp[NUM_FAN][7];
854 u8 pwm_temp_sel[NUM_FAN];
855 u8 pwm_weight_temp_sel[NUM_FAN];
856 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
857 * 2->temp_base
858 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800859
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700860 u8 vid;
861 u8 vrm;
862
Guenter Roeckf73cf632013-03-18 09:22:50 -0700863 bool have_vid;
864
Guenter Roeckaa136e52012-12-04 03:26:05 -0800865 u16 have_temp;
866 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700867 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800868#ifdef CONFIG_PM
869 /* Remember extra register values over suspend/resume */
870 u8 vbat;
871 u8 fandiv1;
872 u8 fandiv2;
873#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700874};
875
876struct nct6775_sio_data {
877 int sioreg;
878 enum kinds kind;
879};
880
Guenter Roeckf73cf632013-03-18 09:22:50 -0700881struct sensor_device_template {
882 struct device_attribute dev_attr;
883 union {
884 struct {
885 u8 nr;
886 u8 index;
887 } s;
888 int index;
889 } u;
890 bool s2; /* true if both index and nr are used */
891};
892
893struct sensor_device_attr_u {
894 union {
895 struct sensor_device_attribute a1;
896 struct sensor_device_attribute_2 a2;
897 } u;
898 char name[32];
899};
900
901#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
902 .attr = {.name = _template, .mode = _mode }, \
903 .show = _show, \
904 .store = _store, \
905}
906
907#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
908 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
909 .u.index = _index, \
910 .s2 = false }
911
912#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
913 _nr, _index) \
914 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
915 .u.s.index = _index, \
916 .u.s.nr = _nr, \
917 .s2 = true }
918
919#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
920static struct sensor_device_template sensor_dev_template_##_name \
921 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
922 _index)
923
924#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
925 _nr, _index) \
926static struct sensor_device_template sensor_dev_template_##_name \
927 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
928 _nr, _index)
929
930struct sensor_template_group {
931 struct sensor_device_template **templates;
932 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
933 int base;
934};
935
936static struct attribute_group *
937nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
938 int repeat)
939{
940 struct attribute_group *group;
941 struct sensor_device_attr_u *su;
942 struct sensor_device_attribute *a;
943 struct sensor_device_attribute_2 *a2;
944 struct attribute **attrs;
945 struct sensor_device_template **t;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300946 int i, count;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700947
948 if (repeat <= 0)
949 return ERR_PTR(-EINVAL);
950
951 t = tg->templates;
952 for (count = 0; *t; t++, count++)
953 ;
954
955 if (count == 0)
956 return ERR_PTR(-EINVAL);
957
958 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
959 if (group == NULL)
960 return ERR_PTR(-ENOMEM);
961
962 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
963 GFP_KERNEL);
964 if (attrs == NULL)
965 return ERR_PTR(-ENOMEM);
966
967 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
968 GFP_KERNEL);
969 if (su == NULL)
970 return ERR_PTR(-ENOMEM);
971
972 group->attrs = attrs;
973 group->is_visible = tg->is_visible;
974
975 for (i = 0; i < repeat; i++) {
976 t = tg->templates;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300977 while (*t != NULL) {
Guenter Roeckf73cf632013-03-18 09:22:50 -0700978 snprintf(su->name, sizeof(su->name),
979 (*t)->dev_attr.attr.name, tg->base + i);
980 if ((*t)->s2) {
981 a2 = &su->u.a2;
982 a2->dev_attr.attr.name = su->name;
983 a2->nr = (*t)->u.s.nr + i;
984 a2->index = (*t)->u.s.index;
985 a2->dev_attr.attr.mode =
986 (*t)->dev_attr.attr.mode;
987 a2->dev_attr.show = (*t)->dev_attr.show;
988 a2->dev_attr.store = (*t)->dev_attr.store;
989 *attrs = &a2->dev_attr.attr;
990 } else {
991 a = &su->u.a1;
992 a->dev_attr.attr.name = su->name;
993 a->index = (*t)->u.index + i;
994 a->dev_attr.attr.mode =
995 (*t)->dev_attr.attr.mode;
996 a->dev_attr.show = (*t)->dev_attr.show;
997 a->dev_attr.store = (*t)->dev_attr.store;
998 *attrs = &a->dev_attr.attr;
999 }
1000 attrs++;
1001 su++;
1002 t++;
1003 }
1004 }
1005
Guenter Roeckf73cf632013-03-18 09:22:50 -07001006 return group;
1007}
1008
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001009static bool is_word_sized(struct nct6775_data *data, u16 reg)
1010{
1011 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07001012 case nct6106:
1013 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1014 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1015 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001016 case nct6775:
1017 return (((reg & 0xff00) == 0x100 ||
1018 (reg & 0xff00) == 0x200) &&
1019 ((reg & 0x00ff) == 0x50 ||
1020 (reg & 0x00ff) == 0x53 ||
1021 (reg & 0x00ff) == 0x55)) ||
1022 (reg & 0xfff0) == 0x630 ||
1023 reg == 0x640 || reg == 0x642 ||
1024 reg == 0x662 ||
1025 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1026 reg == 0x73 || reg == 0x75 || reg == 0x77;
1027 case nct6776:
1028 return (((reg & 0xff00) == 0x100 ||
1029 (reg & 0xff00) == 0x200) &&
1030 ((reg & 0x00ff) == 0x50 ||
1031 (reg & 0x00ff) == 0x53 ||
1032 (reg & 0x00ff) == 0x55)) ||
1033 (reg & 0xfff0) == 0x630 ||
1034 reg == 0x402 ||
1035 reg == 0x640 || reg == 0x642 ||
1036 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1037 reg == 0x73 || reg == 0x75 || reg == 0x77;
1038 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001039 case nct6791:
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001040 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
David Bartley578ab5f2013-06-24 22:28:28 -07001041 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001042 reg == 0x402 ||
1043 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1044 reg == 0x640 || reg == 0x642 ||
1045 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
1046 reg == 0x7b;
1047 }
1048 return false;
1049}
1050
1051/*
1052 * On older chips, only registers 0x50-0x5f are banked.
1053 * On more recent chips, all registers are banked.
1054 * Assume that is the case and set the bank number for each access.
1055 * Cache the bank number so it only needs to be set if it changes.
1056 */
1057static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1058{
1059 u8 bank = reg >> 8;
1060 if (data->bank != bank) {
1061 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1062 outb_p(bank, data->addr + DATA_REG_OFFSET);
1063 data->bank = bank;
1064 }
1065}
1066
1067static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1068{
1069 int res, word_sized = is_word_sized(data, reg);
1070
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001071 nct6775_set_bank(data, reg);
1072 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1073 res = inb_p(data->addr + DATA_REG_OFFSET);
1074 if (word_sized) {
1075 outb_p((reg & 0xff) + 1,
1076 data->addr + ADDR_REG_OFFSET);
1077 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1078 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001079 return res;
1080}
1081
1082static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1083{
1084 int word_sized = is_word_sized(data, reg);
1085
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001086 nct6775_set_bank(data, reg);
1087 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1088 if (word_sized) {
1089 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1090 outb_p((reg & 0xff) + 1,
1091 data->addr + ADDR_REG_OFFSET);
1092 }
1093 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001094 return 0;
1095}
1096
Guenter Roeckaa136e52012-12-04 03:26:05 -08001097/* We left-align 8-bit temperature values to make the code simpler */
1098static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1099{
1100 u16 res;
1101
1102 res = nct6775_read_value(data, reg);
1103 if (!is_word_sized(data, reg))
1104 res <<= 8;
1105
1106 return res;
1107}
1108
1109static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1110{
1111 if (!is_word_sized(data, reg))
1112 value >>= 8;
1113 return nct6775_write_value(data, reg, value);
1114}
1115
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001116/* This function assumes that the caller holds data->update_lock */
1117static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1118{
1119 u8 reg;
1120
1121 switch (nr) {
1122 case 0:
1123 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1124 | (data->fan_div[0] & 0x7);
1125 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1126 break;
1127 case 1:
1128 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1129 | ((data->fan_div[1] << 4) & 0x70);
1130 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1131 break;
1132 case 2:
1133 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1134 | (data->fan_div[2] & 0x7);
1135 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1136 break;
1137 case 3:
1138 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1139 | ((data->fan_div[3] << 4) & 0x70);
1140 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1141 break;
1142 }
1143}
1144
1145static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1146{
1147 if (data->kind == nct6775)
1148 nct6775_write_fan_div(data, nr);
1149}
1150
1151static void nct6775_update_fan_div(struct nct6775_data *data)
1152{
1153 u8 i;
1154
1155 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1156 data->fan_div[0] = i & 0x7;
1157 data->fan_div[1] = (i & 0x70) >> 4;
1158 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1159 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001160 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001161 data->fan_div[3] = (i & 0x70) >> 4;
1162}
1163
1164static void nct6775_update_fan_div_common(struct nct6775_data *data)
1165{
1166 if (data->kind == nct6775)
1167 nct6775_update_fan_div(data);
1168}
1169
1170static void nct6775_init_fan_div(struct nct6775_data *data)
1171{
1172 int i;
1173
1174 nct6775_update_fan_div_common(data);
1175 /*
1176 * For all fans, start with highest divider value if the divider
1177 * register is not initialized. This ensures that we get a
1178 * reading from the fan count register, even if it is not optimal.
1179 * We'll compute a better divider later on.
1180 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001181 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001182 if (!(data->has_fan & (1 << i)))
1183 continue;
1184 if (data->fan_div[i] == 0) {
1185 data->fan_div[i] = 7;
1186 nct6775_write_fan_div_common(data, i);
1187 }
1188 }
1189}
1190
1191static void nct6775_init_fan_common(struct device *dev,
1192 struct nct6775_data *data)
1193{
1194 int i;
1195 u8 reg;
1196
1197 if (data->has_fan_div)
1198 nct6775_init_fan_div(data);
1199
1200 /*
1201 * If fan_min is not set (0), set it to 0xff to disable it. This
1202 * prevents the unnecessary warning when fanX_min is reported as 0.
1203 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001204 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001205 if (data->has_fan_min & (1 << i)) {
1206 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1207 if (!reg)
1208 nct6775_write_value(data, data->REG_FAN_MIN[i],
1209 data->has_fan_div ? 0xff
1210 : 0xff1f);
1211 }
1212 }
1213}
1214
1215static void nct6775_select_fan_div(struct device *dev,
1216 struct nct6775_data *data, int nr, u16 reg)
1217{
1218 u8 fan_div = data->fan_div[nr];
1219 u16 fan_min;
1220
1221 if (!data->has_fan_div)
1222 return;
1223
1224 /*
1225 * If we failed to measure the fan speed, or the reported value is not
1226 * in the optimal range, and the clock divider can be modified,
1227 * let's try that for next time.
1228 */
1229 if (reg == 0x00 && fan_div < 0x07)
1230 fan_div++;
1231 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1232 fan_div--;
1233
1234 if (fan_div != data->fan_div[nr]) {
1235 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1236 nr + 1, div_from_reg(data->fan_div[nr]),
1237 div_from_reg(fan_div));
1238
1239 /* Preserve min limit if possible */
1240 if (data->has_fan_min & (1 << nr)) {
1241 fan_min = data->fan_min[nr];
1242 if (fan_div > data->fan_div[nr]) {
1243 if (fan_min != 255 && fan_min > 1)
1244 fan_min >>= 1;
1245 } else {
1246 if (fan_min != 255) {
1247 fan_min <<= 1;
1248 if (fan_min > 254)
1249 fan_min = 254;
1250 }
1251 }
1252 if (fan_min != data->fan_min[nr]) {
1253 data->fan_min[nr] = fan_min;
1254 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1255 fan_min);
1256 }
1257 }
1258 data->fan_div[nr] = fan_div;
1259 nct6775_write_fan_div_common(data, nr);
1260 }
1261}
1262
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001263static void nct6775_update_pwm(struct device *dev)
1264{
1265 struct nct6775_data *data = dev_get_drvdata(dev);
1266 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001267 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001268 bool duty_is_dc;
1269
1270 for (i = 0; i < data->pwm_num; i++) {
1271 if (!(data->has_pwm & (1 << i)))
1272 continue;
1273
1274 duty_is_dc = data->REG_PWM_MODE[i] &&
1275 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1276 & data->PWM_MODE_MASK[i]);
1277 data->pwm_mode[i] = duty_is_dc;
1278
1279 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1280 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1281 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1282 data->pwm[j][i]
1283 = nct6775_read_value(data,
1284 data->REG_PWM[j][i]);
1285 }
1286 }
1287
1288 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1289 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001290
1291 if (!data->temp_tolerance[0][i] ||
1292 data->pwm_enable[i] != speed_cruise)
1293 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1294 if (!data->target_speed_tolerance[i] ||
1295 data->pwm_enable[i] == speed_cruise) {
1296 u8 t = fanmodecfg & 0x0f;
1297 if (data->REG_TOLERANCE_H) {
1298 t |= (nct6775_read_value(data,
1299 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1300 }
1301 data->target_speed_tolerance[i] = t;
1302 }
1303
1304 data->temp_tolerance[1][i] =
1305 nct6775_read_value(data,
1306 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1307
1308 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1309 data->pwm_temp_sel[i] = reg & 0x1f;
1310 /* If fan can stop, report floor as 0 */
1311 if (reg & 0x80)
1312 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001313
1314 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1315 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1316 /* If weight is disabled, report weight source as 0 */
1317 if (j == 1 && !(reg & 0x80))
1318 data->pwm_weight_temp_sel[i] = 0;
1319
1320 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001321 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001322 data->weight_temp[j][i]
1323 = nct6775_read_value(data,
1324 data->REG_WEIGHT_TEMP[j][i]);
1325 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001326 }
1327}
1328
1329static void nct6775_update_pwm_limits(struct device *dev)
1330{
1331 struct nct6775_data *data = dev_get_drvdata(dev);
1332 int i, j;
1333 u8 reg;
1334 u16 reg_t;
1335
1336 for (i = 0; i < data->pwm_num; i++) {
1337 if (!(data->has_pwm & (1 << i)))
1338 continue;
1339
Guenter Roeckc409fd42013-04-09 05:04:00 -07001340 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001341 data->fan_time[j][i] =
1342 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1343 }
1344
1345 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1346 /* Update only in matching mode or if never updated */
1347 if (!data->target_temp[i] ||
1348 data->pwm_enable[i] == thermal_cruise)
1349 data->target_temp[i] = reg_t & data->target_temp_mask;
1350 if (!data->target_speed[i] ||
1351 data->pwm_enable[i] == speed_cruise) {
1352 if (data->REG_TOLERANCE_H) {
1353 reg_t |= (nct6775_read_value(data,
1354 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1355 }
1356 data->target_speed[i] = reg_t;
1357 }
1358
1359 for (j = 0; j < data->auto_pwm_num; j++) {
1360 data->auto_pwm[i][j] =
1361 nct6775_read_value(data,
1362 NCT6775_AUTO_PWM(data, i, j));
1363 data->auto_temp[i][j] =
1364 nct6775_read_value(data,
1365 NCT6775_AUTO_TEMP(data, i, j));
1366 }
1367
1368 /* critical auto_pwm temperature data */
1369 data->auto_temp[i][data->auto_pwm_num] =
1370 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1371
1372 switch (data->kind) {
1373 case nct6775:
1374 reg = nct6775_read_value(data,
1375 NCT6775_REG_CRITICAL_ENAB[i]);
1376 data->auto_pwm[i][data->auto_pwm_num] =
1377 (reg & 0x02) ? 0xff : 0x00;
1378 break;
1379 case nct6776:
1380 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1381 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001382 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001383 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001384 case nct6791:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001385 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001386 data->REG_CRITICAL_PWM_ENABLE[i]);
1387 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1388 reg = nct6775_read_value(data,
1389 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001390 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001391 reg = 0xff;
1392 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001393 break;
1394 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001395 }
1396}
1397
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001398static struct nct6775_data *nct6775_update_device(struct device *dev)
1399{
1400 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001401 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001402
1403 mutex_lock(&data->update_lock);
1404
Guenter Roeck6445e662013-04-21 09:13:28 -07001405 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001406 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001407 /* Fan clock dividers */
1408 nct6775_update_fan_div_common(data);
1409
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001410 /* Measured voltages and limits */
1411 for (i = 0; i < data->in_num; i++) {
1412 if (!(data->have_in & (1 << i)))
1413 continue;
1414
1415 data->in[i][0] = nct6775_read_value(data,
1416 data->REG_VIN[i]);
1417 data->in[i][1] = nct6775_read_value(data,
1418 data->REG_IN_MINMAX[0][i]);
1419 data->in[i][2] = nct6775_read_value(data,
1420 data->REG_IN_MINMAX[1][i]);
1421 }
1422
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001423 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001424 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001425 u16 reg;
1426
1427 if (!(data->has_fan & (1 << i)))
1428 continue;
1429
1430 reg = nct6775_read_value(data, data->REG_FAN[i]);
1431 data->rpm[i] = data->fan_from_reg(reg,
1432 data->fan_div[i]);
1433
1434 if (data->has_fan_min & (1 << i))
1435 data->fan_min[i] = nct6775_read_value(data,
1436 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001437 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001438 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1439 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001440
1441 nct6775_select_fan_div(dev, data, i, reg);
1442 }
1443
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001444 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001445 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001446
Guenter Roeckaa136e52012-12-04 03:26:05 -08001447 /* Measured temperatures and limits */
1448 for (i = 0; i < NUM_TEMP; i++) {
1449 if (!(data->have_temp & (1 << i)))
1450 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001451 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001452 if (data->reg_temp[j][i])
1453 data->temp[j][i]
1454 = nct6775_read_temp(data,
1455 data->reg_temp[j][i]);
1456 }
Guenter Roeck45a5b3a2013-09-11 10:35:47 -07001457 if (i >= NUM_TEMP_FIXED ||
1458 !(data->have_temp_fixed & (1 << i)))
Guenter Roeckaa136e52012-12-04 03:26:05 -08001459 continue;
1460 data->temp_offset[i]
1461 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1462 }
1463
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001464 data->alarms = 0;
1465 for (i = 0; i < NUM_REG_ALARM; i++) {
1466 u8 alarm;
1467 if (!data->REG_ALARM[i])
1468 continue;
1469 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1470 data->alarms |= ((u64)alarm) << (i << 3);
1471 }
1472
Guenter Roeck30846992013-06-24 22:21:59 -07001473 data->beeps = 0;
1474 for (i = 0; i < NUM_REG_BEEP; i++) {
1475 u8 beep;
1476 if (!data->REG_BEEP[i])
1477 continue;
1478 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1479 data->beeps |= ((u64)beep) << (i << 3);
1480 }
1481
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001482 data->last_updated = jiffies;
1483 data->valid = true;
1484 }
1485
1486 mutex_unlock(&data->update_lock);
1487 return data;
1488}
1489
1490/*
1491 * Sysfs callback functions
1492 */
1493static ssize_t
1494show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1495{
1496 struct nct6775_data *data = nct6775_update_device(dev);
1497 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1498 int nr = sattr->nr;
1499 int index = sattr->index;
1500 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1501}
1502
1503static ssize_t
1504store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1505 size_t count)
1506{
1507 struct nct6775_data *data = dev_get_drvdata(dev);
1508 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1509 int nr = sattr->nr;
1510 int index = sattr->index;
1511 unsigned long val;
1512 int err = kstrtoul(buf, 10, &val);
1513 if (err < 0)
1514 return err;
1515 mutex_lock(&data->update_lock);
1516 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001517 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001518 data->in[nr][index]);
1519 mutex_unlock(&data->update_lock);
1520 return count;
1521}
1522
1523static ssize_t
1524show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1525{
1526 struct nct6775_data *data = nct6775_update_device(dev);
1527 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1528 int nr = data->ALARM_BITS[sattr->index];
1529 return sprintf(buf, "%u\n",
1530 (unsigned int)((data->alarms >> nr) & 0x01));
1531}
1532
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001533static int find_temp_source(struct nct6775_data *data, int index, int count)
1534{
1535 int source = data->temp_src[index];
1536 int nr;
1537
1538 for (nr = 0; nr < count; nr++) {
1539 int src;
1540
1541 src = nct6775_read_value(data,
1542 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1543 if (src == source)
1544 return nr;
1545 }
Guenter Roecke8ab5082013-09-11 10:32:18 -07001546 return -ENODEV;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001547}
1548
1549static ssize_t
1550show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1551{
1552 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1553 struct nct6775_data *data = nct6775_update_device(dev);
1554 unsigned int alarm = 0;
1555 int nr;
1556
1557 /*
1558 * For temperatures, there is no fixed mapping from registers to alarm
1559 * bits. Alarm bits are determined by the temperature source mapping.
1560 */
1561 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1562 if (nr >= 0) {
1563 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1564 alarm = (data->alarms >> bit) & 0x01;
1565 }
1566 return sprintf(buf, "%u\n", alarm);
1567}
1568
Guenter Roeck30846992013-06-24 22:21:59 -07001569static ssize_t
1570show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1571{
1572 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1573 struct nct6775_data *data = nct6775_update_device(dev);
1574 int nr = data->BEEP_BITS[sattr->index];
1575
1576 return sprintf(buf, "%u\n",
1577 (unsigned int)((data->beeps >> nr) & 0x01));
1578}
1579
1580static ssize_t
1581store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1582 size_t count)
1583{
1584 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1585 struct nct6775_data *data = dev_get_drvdata(dev);
1586 int nr = data->BEEP_BITS[sattr->index];
1587 int regindex = nr >> 3;
1588 unsigned long val;
1589
1590 int err = kstrtoul(buf, 10, &val);
1591 if (err < 0)
1592 return err;
1593 if (val > 1)
1594 return -EINVAL;
1595
1596 mutex_lock(&data->update_lock);
1597 if (val)
1598 data->beeps |= (1ULL << nr);
1599 else
1600 data->beeps &= ~(1ULL << nr);
1601 nct6775_write_value(data, data->REG_BEEP[regindex],
1602 (data->beeps >> (regindex << 3)) & 0xff);
1603 mutex_unlock(&data->update_lock);
1604 return count;
1605}
1606
1607static ssize_t
1608show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1609{
1610 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1611 struct nct6775_data *data = nct6775_update_device(dev);
1612 unsigned int beep = 0;
1613 int nr;
1614
1615 /*
1616 * For temperatures, there is no fixed mapping from registers to beep
1617 * enable bits. Beep enable bits are determined by the temperature
1618 * source mapping.
1619 */
1620 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1621 if (nr >= 0) {
1622 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1623 beep = (data->beeps >> bit) & 0x01;
1624 }
1625 return sprintf(buf, "%u\n", beep);
1626}
1627
1628static ssize_t
1629store_temp_beep(struct device *dev, struct device_attribute *attr,
1630 const char *buf, size_t count)
1631{
1632 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1633 struct nct6775_data *data = dev_get_drvdata(dev);
1634 int nr, bit, regindex;
1635 unsigned long val;
1636
1637 int err = kstrtoul(buf, 10, &val);
1638 if (err < 0)
1639 return err;
1640 if (val > 1)
1641 return -EINVAL;
1642
1643 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1644 if (nr < 0)
Guenter Roecke8ab5082013-09-11 10:32:18 -07001645 return nr;
Guenter Roeck30846992013-06-24 22:21:59 -07001646
1647 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1648 regindex = bit >> 3;
1649
1650 mutex_lock(&data->update_lock);
1651 if (val)
1652 data->beeps |= (1ULL << bit);
1653 else
1654 data->beeps &= ~(1ULL << bit);
1655 nct6775_write_value(data, data->REG_BEEP[regindex],
1656 (data->beeps >> (regindex << 3)) & 0xff);
1657 mutex_unlock(&data->update_lock);
1658
1659 return count;
1660}
1661
Guenter Roeckf73cf632013-03-18 09:22:50 -07001662static umode_t nct6775_in_is_visible(struct kobject *kobj,
1663 struct attribute *attr, int index)
1664{
1665 struct device *dev = container_of(kobj, struct device, kobj);
1666 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001667 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001668
Guenter Roeckf73cf632013-03-18 09:22:50 -07001669 if (!(data->have_in & (1 << in)))
1670 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001671
Guenter Roeckf73cf632013-03-18 09:22:50 -07001672 return attr->mode;
1673}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001674
Guenter Roeckf73cf632013-03-18 09:22:50 -07001675SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1676SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001677SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1678 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001679SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1680 store_in_reg, 0, 1);
1681SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1682 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001683
Guenter Roeckf73cf632013-03-18 09:22:50 -07001684/*
1685 * nct6775_in_is_visible uses the index into the following array
1686 * to determine if attributes should be created or not.
1687 * Any change in order or content must be matched.
1688 */
1689static struct sensor_device_template *nct6775_attributes_in_template[] = {
1690 &sensor_dev_template_in_input,
1691 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001692 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001693 &sensor_dev_template_in_min,
1694 &sensor_dev_template_in_max,
1695 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001696};
1697
Guenter Roeckf73cf632013-03-18 09:22:50 -07001698static struct sensor_template_group nct6775_in_template_group = {
1699 .templates = nct6775_attributes_in_template,
1700 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001701};
1702
1703static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001704show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1705{
1706 struct nct6775_data *data = nct6775_update_device(dev);
1707 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1708 int nr = sattr->index;
1709 return sprintf(buf, "%d\n", data->rpm[nr]);
1710}
1711
1712static ssize_t
1713show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1714{
1715 struct nct6775_data *data = nct6775_update_device(dev);
1716 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1717 int nr = sattr->index;
1718 return sprintf(buf, "%d\n",
1719 data->fan_from_reg_min(data->fan_min[nr],
1720 data->fan_div[nr]));
1721}
1722
1723static ssize_t
1724show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1725{
1726 struct nct6775_data *data = nct6775_update_device(dev);
1727 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1728 int nr = sattr->index;
1729 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1730}
1731
1732static ssize_t
1733store_fan_min(struct device *dev, struct device_attribute *attr,
1734 const char *buf, size_t count)
1735{
1736 struct nct6775_data *data = dev_get_drvdata(dev);
1737 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1738 int nr = sattr->index;
1739 unsigned long val;
1740 int err;
1741 unsigned int reg;
1742 u8 new_div;
1743
1744 err = kstrtoul(buf, 10, &val);
1745 if (err < 0)
1746 return err;
1747
1748 mutex_lock(&data->update_lock);
1749 if (!data->has_fan_div) {
1750 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1751 if (!val) {
1752 val = 0xff1f;
1753 } else {
1754 if (val > 1350000U)
1755 val = 135000U;
1756 val = 1350000U / val;
1757 val = (val & 0x1f) | ((val << 3) & 0xff00);
1758 }
1759 data->fan_min[nr] = val;
1760 goto write_min; /* Leave fan divider alone */
1761 }
1762 if (!val) {
1763 /* No min limit, alarm disabled */
1764 data->fan_min[nr] = 255;
1765 new_div = data->fan_div[nr]; /* No change */
1766 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1767 goto write_div;
1768 }
1769 reg = 1350000U / val;
1770 if (reg >= 128 * 255) {
1771 /*
1772 * Speed below this value cannot possibly be represented,
1773 * even with the highest divider (128)
1774 */
1775 data->fan_min[nr] = 254;
1776 new_div = 7; /* 128 == (1 << 7) */
1777 dev_warn(dev,
1778 "fan%u low limit %lu below minimum %u, set to minimum\n",
1779 nr + 1, val, data->fan_from_reg_min(254, 7));
1780 } else if (!reg) {
1781 /*
1782 * Speed above this value cannot possibly be represented,
1783 * even with the lowest divider (1)
1784 */
1785 data->fan_min[nr] = 1;
1786 new_div = 0; /* 1 == (1 << 0) */
1787 dev_warn(dev,
1788 "fan%u low limit %lu above maximum %u, set to maximum\n",
1789 nr + 1, val, data->fan_from_reg_min(1, 0));
1790 } else {
1791 /*
1792 * Automatically pick the best divider, i.e. the one such
1793 * that the min limit will correspond to a register value
1794 * in the 96..192 range
1795 */
1796 new_div = 0;
1797 while (reg > 192 && new_div < 7) {
1798 reg >>= 1;
1799 new_div++;
1800 }
1801 data->fan_min[nr] = reg;
1802 }
1803
1804write_div:
1805 /*
1806 * Write both the fan clock divider (if it changed) and the new
1807 * fan min (unconditionally)
1808 */
1809 if (new_div != data->fan_div[nr]) {
1810 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1811 nr + 1, div_from_reg(data->fan_div[nr]),
1812 div_from_reg(new_div));
1813 data->fan_div[nr] = new_div;
1814 nct6775_write_fan_div_common(data, nr);
1815 /* Give the chip time to sample a new speed value */
1816 data->last_updated = jiffies;
1817 }
1818
1819write_min:
1820 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1821 mutex_unlock(&data->update_lock);
1822
1823 return count;
1824}
1825
Guenter Roeck5c25d952012-12-11 07:29:06 -08001826static ssize_t
1827show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1828{
1829 struct nct6775_data *data = nct6775_update_device(dev);
1830 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1831 int p = data->fan_pulses[sattr->index];
1832
1833 return sprintf(buf, "%d\n", p ? : 4);
1834}
1835
1836static ssize_t
1837store_fan_pulses(struct device *dev, struct device_attribute *attr,
1838 const char *buf, size_t count)
1839{
1840 struct nct6775_data *data = dev_get_drvdata(dev);
1841 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1842 int nr = sattr->index;
1843 unsigned long val;
1844 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001845 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001846
1847 err = kstrtoul(buf, 10, &val);
1848 if (err < 0)
1849 return err;
1850
1851 if (val > 4)
1852 return -EINVAL;
1853
1854 mutex_lock(&data->update_lock);
1855 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001856 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1857 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1858 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1859 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001860 mutex_unlock(&data->update_lock);
1861
1862 return count;
1863}
1864
Guenter Roeckf73cf632013-03-18 09:22:50 -07001865static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1866 struct attribute *attr, int index)
1867{
1868 struct device *dev = container_of(kobj, struct device, kobj);
1869 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001870 int fan = index / 6; /* fan index */
1871 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001872
1873 if (!(data->has_fan & (1 << fan)))
1874 return 0;
1875
1876 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1877 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001878 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001879 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001880 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1881 return 0;
1882 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001883 return 0;
1884
1885 return attr->mode;
1886}
1887
1888SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1889SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1890 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001891SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1892 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001893SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1894 store_fan_pulses, 0);
1895SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1896 store_fan_min, 0);
1897SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1898
1899/*
1900 * nct6775_fan_is_visible uses the index into the following array
1901 * to determine if attributes should be created or not.
1902 * Any change in order or content must be matched.
1903 */
1904static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1905 &sensor_dev_template_fan_input,
1906 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001907 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001908 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001909 &sensor_dev_template_fan_min, /* 4 */
1910 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001911 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001912};
1913
Guenter Roeckf73cf632013-03-18 09:22:50 -07001914static struct sensor_template_group nct6775_fan_template_group = {
1915 .templates = nct6775_attributes_fan_template,
1916 .is_visible = nct6775_fan_is_visible,
1917 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001918};
1919
1920static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001921show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1922{
1923 struct nct6775_data *data = nct6775_update_device(dev);
1924 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1925 int nr = sattr->index;
1926 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1927}
1928
1929static ssize_t
1930show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1931{
1932 struct nct6775_data *data = nct6775_update_device(dev);
1933 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1934 int nr = sattr->nr;
1935 int index = sattr->index;
1936
1937 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1938}
1939
1940static ssize_t
1941store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1942 size_t count)
1943{
1944 struct nct6775_data *data = dev_get_drvdata(dev);
1945 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1946 int nr = sattr->nr;
1947 int index = sattr->index;
1948 int err;
1949 long val;
1950
1951 err = kstrtol(buf, 10, &val);
1952 if (err < 0)
1953 return err;
1954
1955 mutex_lock(&data->update_lock);
1956 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1957 nct6775_write_temp(data, data->reg_temp[index][nr],
1958 data->temp[index][nr]);
1959 mutex_unlock(&data->update_lock);
1960 return count;
1961}
1962
1963static ssize_t
1964show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1965{
1966 struct nct6775_data *data = nct6775_update_device(dev);
1967 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1968
1969 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1970}
1971
1972static ssize_t
1973store_temp_offset(struct device *dev, struct device_attribute *attr,
1974 const char *buf, size_t count)
1975{
1976 struct nct6775_data *data = dev_get_drvdata(dev);
1977 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1978 int nr = sattr->index;
1979 long val;
1980 int err;
1981
1982 err = kstrtol(buf, 10, &val);
1983 if (err < 0)
1984 return err;
1985
1986 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1987
1988 mutex_lock(&data->update_lock);
1989 data->temp_offset[nr] = val;
1990 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1991 mutex_unlock(&data->update_lock);
1992
1993 return count;
1994}
1995
1996static ssize_t
1997show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1998{
1999 struct nct6775_data *data = nct6775_update_device(dev);
2000 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2001 int nr = sattr->index;
2002 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2003}
2004
2005static ssize_t
2006store_temp_type(struct device *dev, struct device_attribute *attr,
2007 const char *buf, size_t count)
2008{
2009 struct nct6775_data *data = nct6775_update_device(dev);
2010 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2011 int nr = sattr->index;
2012 unsigned long val;
2013 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002014 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002015
2016 err = kstrtoul(buf, 10, &val);
2017 if (err < 0)
2018 return err;
2019
2020 if (val != 1 && val != 3 && val != 4)
2021 return -EINVAL;
2022
2023 mutex_lock(&data->update_lock);
2024
2025 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002026 vbit = 0x02 << nr;
2027 dbit = data->DIODE_MASK << nr;
2028 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2029 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002030 switch (val) {
2031 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002032 vbat |= vbit;
2033 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002034 break;
2035 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002036 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002037 break;
2038 case 4: /* thermistor */
2039 break;
2040 }
2041 nct6775_write_value(data, data->REG_VBAT, vbat);
2042 nct6775_write_value(data, data->REG_DIODE, diode);
2043
2044 mutex_unlock(&data->update_lock);
2045 return count;
2046}
2047
Guenter Roeckf73cf632013-03-18 09:22:50 -07002048static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2049 struct attribute *attr, int index)
2050{
2051 struct device *dev = container_of(kobj, struct device, kobj);
2052 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002053 int temp = index / 10; /* temp index */
2054 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002055
2056 if (!(data->have_temp & (1 << temp)))
2057 return 0;
2058
2059 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2060 return 0; /* alarm */
2061
Guenter Roeck30846992013-06-24 22:21:59 -07002062 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2063 return 0; /* beep */
2064
2065 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002066 return 0;
2067
Guenter Roeck30846992013-06-24 22:21:59 -07002068 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002069 return 0;
2070
Guenter Roeck30846992013-06-24 22:21:59 -07002071 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002072 return 0;
2073
Guenter Roeck30846992013-06-24 22:21:59 -07002074 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002075 return 0;
2076
2077 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002078 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002079 return 0;
2080
2081 return attr->mode;
2082}
2083
2084SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2085SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2086SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2087 store_temp, 0, 1);
2088SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2089 show_temp, store_temp, 0, 2);
2090SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2091 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002092SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2093 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002094SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2095 show_temp_offset, store_temp_offset, 0);
2096SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2097 store_temp_type, 0);
2098SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002099SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2100 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002101
2102/*
2103 * nct6775_temp_is_visible uses the index into the following array
2104 * to determine if attributes should be created or not.
2105 * Any change in order or content must be matched.
2106 */
2107static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2108 &sensor_dev_template_temp_input,
2109 &sensor_dev_template_temp_label,
2110 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002111 &sensor_dev_template_temp_beep, /* 3 */
2112 &sensor_dev_template_temp_max, /* 4 */
2113 &sensor_dev_template_temp_max_hyst, /* 5 */
2114 &sensor_dev_template_temp_crit, /* 6 */
2115 &sensor_dev_template_temp_lcrit, /* 7 */
2116 &sensor_dev_template_temp_offset, /* 8 */
2117 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002118 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002119};
2120
Guenter Roeckf73cf632013-03-18 09:22:50 -07002121static struct sensor_template_group nct6775_temp_template_group = {
2122 .templates = nct6775_attributes_temp_template,
2123 .is_visible = nct6775_temp_is_visible,
2124 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002125};
2126
Guenter Roeckaa136e52012-12-04 03:26:05 -08002127static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002128show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2129{
2130 struct nct6775_data *data = nct6775_update_device(dev);
2131 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2132
2133 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2134}
2135
2136static ssize_t
2137store_pwm_mode(struct device *dev, struct device_attribute *attr,
2138 const char *buf, size_t count)
2139{
2140 struct nct6775_data *data = dev_get_drvdata(dev);
2141 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2142 int nr = sattr->index;
2143 unsigned long val;
2144 int err;
2145 u8 reg;
2146
2147 err = kstrtoul(buf, 10, &val);
2148 if (err < 0)
2149 return err;
2150
2151 if (val > 1)
2152 return -EINVAL;
2153
2154 /* Setting DC mode is not supported for all chips/channels */
2155 if (data->REG_PWM_MODE[nr] == 0) {
2156 if (val)
2157 return -EINVAL;
2158 return count;
2159 }
2160
2161 mutex_lock(&data->update_lock);
2162 data->pwm_mode[nr] = val;
2163 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2164 reg &= ~data->PWM_MODE_MASK[nr];
2165 if (val)
2166 reg |= data->PWM_MODE_MASK[nr];
2167 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2168 mutex_unlock(&data->update_lock);
2169 return count;
2170}
2171
2172static ssize_t
2173show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2174{
2175 struct nct6775_data *data = nct6775_update_device(dev);
2176 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2177 int nr = sattr->nr;
2178 int index = sattr->index;
2179 int pwm;
2180
2181 /*
2182 * For automatic fan control modes, show current pwm readings.
2183 * Otherwise, show the configured value.
2184 */
2185 if (index == 0 && data->pwm_enable[nr] > manual)
2186 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2187 else
2188 pwm = data->pwm[index][nr];
2189
2190 return sprintf(buf, "%d\n", pwm);
2191}
2192
2193static ssize_t
2194store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2195 size_t count)
2196{
2197 struct nct6775_data *data = dev_get_drvdata(dev);
2198 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2199 int nr = sattr->nr;
2200 int index = sattr->index;
2201 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002202 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2203 int maxval[7]
2204 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002205 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002206 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002207
2208 err = kstrtoul(buf, 10, &val);
2209 if (err < 0)
2210 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002211 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002212
2213 mutex_lock(&data->update_lock);
2214 data->pwm[index][nr] = val;
2215 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002216 if (index == 2) { /* floor: disable if val == 0 */
2217 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2218 reg &= 0x7f;
2219 if (val)
2220 reg |= 0x80;
2221 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2222 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002223 mutex_unlock(&data->update_lock);
2224 return count;
2225}
2226
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002227/* Returns 0 if OK, -EINVAL otherwise */
2228static int check_trip_points(struct nct6775_data *data, int nr)
2229{
2230 int i;
2231
2232 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2233 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2234 return -EINVAL;
2235 }
2236 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2237 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2238 return -EINVAL;
2239 }
2240 /* validate critical temperature and pwm if enabled (pwm > 0) */
2241 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2242 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2243 data->auto_temp[nr][data->auto_pwm_num] ||
2244 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2245 data->auto_pwm[nr][data->auto_pwm_num])
2246 return -EINVAL;
2247 }
2248 return 0;
2249}
2250
2251static void pwm_update_registers(struct nct6775_data *data, int nr)
2252{
2253 u8 reg;
2254
2255 switch (data->pwm_enable[nr]) {
2256 case off:
2257 case manual:
2258 break;
2259 case speed_cruise:
2260 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2261 reg = (reg & ~data->tolerance_mask) |
2262 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2263 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2264 nct6775_write_value(data, data->REG_TARGET[nr],
2265 data->target_speed[nr] & 0xff);
2266 if (data->REG_TOLERANCE_H) {
2267 reg = (data->target_speed[nr] >> 8) & 0x0f;
2268 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2269 nct6775_write_value(data,
2270 data->REG_TOLERANCE_H[nr],
2271 reg);
2272 }
2273 break;
2274 case thermal_cruise:
2275 nct6775_write_value(data, data->REG_TARGET[nr],
2276 data->target_temp[nr]);
2277 /* intentional */
2278 default:
2279 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2280 reg = (reg & ~data->tolerance_mask) |
2281 data->temp_tolerance[0][nr];
2282 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2283 break;
2284 }
2285}
2286
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002287static ssize_t
2288show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2289{
2290 struct nct6775_data *data = nct6775_update_device(dev);
2291 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2292
2293 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2294}
2295
2296static ssize_t
2297store_pwm_enable(struct device *dev, struct device_attribute *attr,
2298 const char *buf, size_t count)
2299{
2300 struct nct6775_data *data = dev_get_drvdata(dev);
2301 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2302 int nr = sattr->index;
2303 unsigned long val;
2304 int err;
2305 u16 reg;
2306
2307 err = kstrtoul(buf, 10, &val);
2308 if (err < 0)
2309 return err;
2310
2311 if (val > sf4)
2312 return -EINVAL;
2313
2314 if (val == sf3 && data->kind != nct6775)
2315 return -EINVAL;
2316
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002317 if (val == sf4 && check_trip_points(data, nr)) {
2318 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2319 dev_err(dev, "Adjust trip points and try again\n");
2320 return -EINVAL;
2321 }
2322
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002323 mutex_lock(&data->update_lock);
2324 data->pwm_enable[nr] = val;
2325 if (val == off) {
2326 /*
2327 * turn off pwm control: select manual mode, set pwm to maximum
2328 */
2329 data->pwm[0][nr] = 255;
2330 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2331 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002332 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002333 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2334 reg &= 0x0f;
2335 reg |= pwm_enable_to_reg(val) << 4;
2336 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2337 mutex_unlock(&data->update_lock);
2338 return count;
2339}
2340
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002341static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002342show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002343{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002344 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002345
2346 for (i = 0; i < NUM_TEMP; i++) {
2347 if (!(data->have_temp & (1 << i)))
2348 continue;
2349 if (src == data->temp_src[i]) {
2350 sel = i + 1;
2351 break;
2352 }
2353 }
2354
2355 return sprintf(buf, "%d\n", sel);
2356}
2357
2358static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002359show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2360{
2361 struct nct6775_data *data = nct6775_update_device(dev);
2362 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2363 int index = sattr->index;
2364
2365 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2366}
2367
2368static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002369store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2370 const char *buf, size_t count)
2371{
2372 struct nct6775_data *data = nct6775_update_device(dev);
2373 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2374 int nr = sattr->index;
2375 unsigned long val;
2376 int err, reg, src;
2377
2378 err = kstrtoul(buf, 10, &val);
2379 if (err < 0)
2380 return err;
2381 if (val == 0 || val > NUM_TEMP)
2382 return -EINVAL;
2383 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2384 return -EINVAL;
2385
2386 mutex_lock(&data->update_lock);
2387 src = data->temp_src[val - 1];
2388 data->pwm_temp_sel[nr] = src;
2389 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2390 reg &= 0xe0;
2391 reg |= src;
2392 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2393 mutex_unlock(&data->update_lock);
2394
2395 return count;
2396}
2397
2398static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002399show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2400 char *buf)
2401{
2402 struct nct6775_data *data = nct6775_update_device(dev);
2403 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2404 int index = sattr->index;
2405
2406 return show_pwm_temp_sel_common(data, buf,
2407 data->pwm_weight_temp_sel[index]);
2408}
2409
2410static ssize_t
2411store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2412 const char *buf, size_t count)
2413{
2414 struct nct6775_data *data = nct6775_update_device(dev);
2415 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2416 int nr = sattr->index;
2417 unsigned long val;
2418 int err, reg, src;
2419
2420 err = kstrtoul(buf, 10, &val);
2421 if (err < 0)
2422 return err;
2423 if (val > NUM_TEMP)
2424 return -EINVAL;
2425 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2426 !data->temp_src[val - 1]))
2427 return -EINVAL;
2428
2429 mutex_lock(&data->update_lock);
2430 if (val) {
2431 src = data->temp_src[val - 1];
2432 data->pwm_weight_temp_sel[nr] = src;
2433 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2434 reg &= 0xe0;
2435 reg |= (src | 0x80);
2436 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2437 } else {
2438 data->pwm_weight_temp_sel[nr] = 0;
2439 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2440 reg &= 0x7f;
2441 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2442 }
2443 mutex_unlock(&data->update_lock);
2444
2445 return count;
2446}
2447
2448static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002449show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2450{
2451 struct nct6775_data *data = nct6775_update_device(dev);
2452 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2453
2454 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2455}
2456
2457static ssize_t
2458store_target_temp(struct device *dev, struct device_attribute *attr,
2459 const char *buf, size_t count)
2460{
2461 struct nct6775_data *data = dev_get_drvdata(dev);
2462 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2463 int nr = sattr->index;
2464 unsigned long val;
2465 int err;
2466
2467 err = kstrtoul(buf, 10, &val);
2468 if (err < 0)
2469 return err;
2470
2471 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2472 data->target_temp_mask);
2473
2474 mutex_lock(&data->update_lock);
2475 data->target_temp[nr] = val;
2476 pwm_update_registers(data, nr);
2477 mutex_unlock(&data->update_lock);
2478 return count;
2479}
2480
2481static ssize_t
2482show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2483{
2484 struct nct6775_data *data = nct6775_update_device(dev);
2485 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2486 int nr = sattr->index;
2487
2488 return sprintf(buf, "%d\n",
2489 fan_from_reg16(data->target_speed[nr],
2490 data->fan_div[nr]));
2491}
2492
2493static ssize_t
2494store_target_speed(struct device *dev, struct device_attribute *attr,
2495 const char *buf, size_t count)
2496{
2497 struct nct6775_data *data = dev_get_drvdata(dev);
2498 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2499 int nr = sattr->index;
2500 unsigned long val;
2501 int err;
2502 u16 speed;
2503
2504 err = kstrtoul(buf, 10, &val);
2505 if (err < 0)
2506 return err;
2507
2508 val = clamp_val(val, 0, 1350000U);
2509 speed = fan_to_reg(val, data->fan_div[nr]);
2510
2511 mutex_lock(&data->update_lock);
2512 data->target_speed[nr] = speed;
2513 pwm_update_registers(data, nr);
2514 mutex_unlock(&data->update_lock);
2515 return count;
2516}
2517
2518static ssize_t
2519show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2520 char *buf)
2521{
2522 struct nct6775_data *data = nct6775_update_device(dev);
2523 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2524 int nr = sattr->nr;
2525 int index = sattr->index;
2526
2527 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2528}
2529
2530static ssize_t
2531store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2532 const char *buf, size_t count)
2533{
2534 struct nct6775_data *data = dev_get_drvdata(dev);
2535 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2536 int nr = sattr->nr;
2537 int index = sattr->index;
2538 unsigned long val;
2539 int err;
2540
2541 err = kstrtoul(buf, 10, &val);
2542 if (err < 0)
2543 return err;
2544
2545 /* Limit tolerance as needed */
2546 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2547
2548 mutex_lock(&data->update_lock);
2549 data->temp_tolerance[index][nr] = val;
2550 if (index)
2551 pwm_update_registers(data, nr);
2552 else
2553 nct6775_write_value(data,
2554 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2555 val);
2556 mutex_unlock(&data->update_lock);
2557 return count;
2558}
2559
2560/*
2561 * Fan speed tolerance is a tricky beast, since the associated register is
2562 * a tick counter, but the value is reported and configured as rpm.
2563 * Compute resulting low and high rpm values and report the difference.
2564 */
2565static ssize_t
2566show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2567 char *buf)
2568{
2569 struct nct6775_data *data = nct6775_update_device(dev);
2570 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2571 int nr = sattr->index;
2572 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2573 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2574 int tolerance;
2575
2576 if (low <= 0)
2577 low = 1;
2578 if (high > 0xffff)
2579 high = 0xffff;
2580 if (high < low)
2581 high = low;
2582
2583 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2584 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2585
2586 return sprintf(buf, "%d\n", tolerance);
2587}
2588
2589static ssize_t
2590store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2591 const char *buf, size_t count)
2592{
2593 struct nct6775_data *data = dev_get_drvdata(dev);
2594 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2595 int nr = sattr->index;
2596 unsigned long val;
2597 int err;
2598 int low, high;
2599
2600 err = kstrtoul(buf, 10, &val);
2601 if (err < 0)
2602 return err;
2603
2604 high = fan_from_reg16(data->target_speed[nr],
2605 data->fan_div[nr]) + val;
2606 low = fan_from_reg16(data->target_speed[nr],
2607 data->fan_div[nr]) - val;
2608 if (low <= 0)
2609 low = 1;
2610 if (high < low)
2611 high = low;
2612
2613 val = (fan_to_reg(low, data->fan_div[nr]) -
2614 fan_to_reg(high, data->fan_div[nr])) / 2;
2615
2616 /* Limit tolerance as needed */
2617 val = clamp_val(val, 0, data->speed_tolerance_limit);
2618
2619 mutex_lock(&data->update_lock);
2620 data->target_speed_tolerance[nr] = val;
2621 pwm_update_registers(data, nr);
2622 mutex_unlock(&data->update_lock);
2623 return count;
2624}
2625
Guenter Roeckf73cf632013-03-18 09:22:50 -07002626SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2627SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2628 store_pwm_mode, 0);
2629SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2630 store_pwm_enable, 0);
2631SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2632 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2633SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2634 show_target_temp, store_target_temp, 0);
2635SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2636 show_target_speed, store_target_speed, 0);
2637SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2638 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002639
2640/* Smart Fan registers */
2641
2642static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002643show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2644{
2645 struct nct6775_data *data = nct6775_update_device(dev);
2646 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2647 int nr = sattr->nr;
2648 int index = sattr->index;
2649
2650 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2651}
2652
2653static ssize_t
2654store_weight_temp(struct device *dev, struct device_attribute *attr,
2655 const char *buf, size_t count)
2656{
2657 struct nct6775_data *data = dev_get_drvdata(dev);
2658 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2659 int nr = sattr->nr;
2660 int index = sattr->index;
2661 unsigned long val;
2662 int err;
2663
2664 err = kstrtoul(buf, 10, &val);
2665 if (err < 0)
2666 return err;
2667
2668 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2669
2670 mutex_lock(&data->update_lock);
2671 data->weight_temp[index][nr] = val;
2672 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2673 mutex_unlock(&data->update_lock);
2674 return count;
2675}
2676
Guenter Roeckf73cf632013-03-18 09:22:50 -07002677SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2678 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2679SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2680 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2681SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2682 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2683SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2684 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2685SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2686 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2687SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2688 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002689
2690static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002691show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2692{
2693 struct nct6775_data *data = nct6775_update_device(dev);
2694 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2695 int nr = sattr->nr;
2696 int index = sattr->index;
2697
2698 return sprintf(buf, "%d\n",
2699 step_time_from_reg(data->fan_time[index][nr],
2700 data->pwm_mode[nr]));
2701}
2702
2703static ssize_t
2704store_fan_time(struct device *dev, struct device_attribute *attr,
2705 const char *buf, size_t count)
2706{
2707 struct nct6775_data *data = dev_get_drvdata(dev);
2708 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2709 int nr = sattr->nr;
2710 int index = sattr->index;
2711 unsigned long val;
2712 int err;
2713
2714 err = kstrtoul(buf, 10, &val);
2715 if (err < 0)
2716 return err;
2717
2718 val = step_time_to_reg(val, data->pwm_mode[nr]);
2719 mutex_lock(&data->update_lock);
2720 data->fan_time[index][nr] = val;
2721 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2722 mutex_unlock(&data->update_lock);
2723 return count;
2724}
2725
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002726static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002727show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2728{
2729 struct nct6775_data *data = nct6775_update_device(dev);
2730 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2731
2732 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2733}
2734
2735static ssize_t
2736store_auto_pwm(struct device *dev, struct device_attribute *attr,
2737 const char *buf, size_t count)
2738{
2739 struct nct6775_data *data = dev_get_drvdata(dev);
2740 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2741 int nr = sattr->nr;
2742 int point = sattr->index;
2743 unsigned long val;
2744 int err;
2745 u8 reg;
2746
2747 err = kstrtoul(buf, 10, &val);
2748 if (err < 0)
2749 return err;
2750 if (val > 255)
2751 return -EINVAL;
2752
2753 if (point == data->auto_pwm_num) {
2754 if (data->kind != nct6775 && !val)
2755 return -EINVAL;
2756 if (data->kind != nct6779 && val)
2757 val = 0xff;
2758 }
2759
2760 mutex_lock(&data->update_lock);
2761 data->auto_pwm[nr][point] = val;
2762 if (point < data->auto_pwm_num) {
2763 nct6775_write_value(data,
2764 NCT6775_AUTO_PWM(data, nr, point),
2765 data->auto_pwm[nr][point]);
2766 } else {
2767 switch (data->kind) {
2768 case nct6775:
2769 /* disable if needed (pwm == 0) */
2770 reg = nct6775_read_value(data,
2771 NCT6775_REG_CRITICAL_ENAB[nr]);
2772 if (val)
2773 reg |= 0x02;
2774 else
2775 reg &= ~0x02;
2776 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2777 reg);
2778 break;
2779 case nct6776:
2780 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002781 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002782 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002783 case nct6791:
Guenter Roeck6c009502012-07-01 08:23:15 -07002784 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002785 val);
2786 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002787 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002788 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002789 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002790 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002791 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002792 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002793 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002794 reg);
2795 break;
2796 }
2797 }
2798 mutex_unlock(&data->update_lock);
2799 return count;
2800}
2801
2802static ssize_t
2803show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2804{
2805 struct nct6775_data *data = nct6775_update_device(dev);
2806 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2807 int nr = sattr->nr;
2808 int point = sattr->index;
2809
2810 /*
2811 * We don't know for sure if the temperature is signed or unsigned.
2812 * Assume it is unsigned.
2813 */
2814 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2815}
2816
2817static ssize_t
2818store_auto_temp(struct device *dev, struct device_attribute *attr,
2819 const char *buf, size_t count)
2820{
2821 struct nct6775_data *data = dev_get_drvdata(dev);
2822 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2823 int nr = sattr->nr;
2824 int point = sattr->index;
2825 unsigned long val;
2826 int err;
2827
2828 err = kstrtoul(buf, 10, &val);
2829 if (err)
2830 return err;
2831 if (val > 255000)
2832 return -EINVAL;
2833
2834 mutex_lock(&data->update_lock);
2835 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2836 if (point < data->auto_pwm_num) {
2837 nct6775_write_value(data,
2838 NCT6775_AUTO_TEMP(data, nr, point),
2839 data->auto_temp[nr][point]);
2840 } else {
2841 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2842 data->auto_temp[nr][point]);
2843 }
2844 mutex_unlock(&data->update_lock);
2845 return count;
2846}
2847
Guenter Roeckf73cf632013-03-18 09:22:50 -07002848static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2849 struct attribute *attr, int index)
2850{
2851 struct device *dev = container_of(kobj, struct device, kobj);
2852 struct nct6775_data *data = dev_get_drvdata(dev);
2853 int pwm = index / 36; /* pwm index */
2854 int nr = index % 36; /* attribute index */
2855
2856 if (!(data->has_pwm & (1 << pwm)))
2857 return 0;
2858
2859 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2860 return 0;
2861 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2862 return 0;
2863 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2864 return 0;
2865
2866 if (nr >= 22 && nr <= 35) { /* auto point */
2867 int api = (nr - 22) / 2; /* auto point index */
2868
2869 if (api > data->auto_pwm_num)
2870 return 0;
2871 }
2872 return attr->mode;
2873}
2874
2875SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2876 show_fan_time, store_fan_time, 0, 0);
2877SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2878 show_fan_time, store_fan_time, 0, 1);
2879SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2880 show_fan_time, store_fan_time, 0, 2);
2881SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2882 store_pwm, 0, 1);
2883SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2884 store_pwm, 0, 2);
2885SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2886 show_temp_tolerance, store_temp_tolerance, 0, 0);
2887SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2888 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2889 0, 1);
2890
2891SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2892 0, 3);
2893
2894SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2895 store_pwm, 0, 4);
2896
2897SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2898 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2899SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2900 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2901
2902SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2903 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2904SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2905 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2906
2907SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2908 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2909SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2910 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2911
2912SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2913 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2914SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2915 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2916
2917SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2918 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2919SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2920 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2921
2922SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2923 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2924SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2925 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2926
2927SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2928 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2929SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2930 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2931
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002932/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002933 * nct6775_pwm_is_visible uses the index into the following array
2934 * to determine if attributes should be created or not.
2935 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002936 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002937static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2938 &sensor_dev_template_pwm,
2939 &sensor_dev_template_pwm_mode,
2940 &sensor_dev_template_pwm_enable,
2941 &sensor_dev_template_pwm_temp_sel,
2942 &sensor_dev_template_pwm_temp_tolerance,
2943 &sensor_dev_template_pwm_crit_temp_tolerance,
2944 &sensor_dev_template_pwm_target_temp,
2945 &sensor_dev_template_fan_target,
2946 &sensor_dev_template_fan_tolerance,
2947 &sensor_dev_template_pwm_stop_time,
2948 &sensor_dev_template_pwm_step_up_time,
2949 &sensor_dev_template_pwm_step_down_time,
2950 &sensor_dev_template_pwm_start,
2951 &sensor_dev_template_pwm_floor,
2952 &sensor_dev_template_pwm_weight_temp_sel,
2953 &sensor_dev_template_pwm_weight_temp_step,
2954 &sensor_dev_template_pwm_weight_temp_step_tol,
2955 &sensor_dev_template_pwm_weight_temp_step_base,
2956 &sensor_dev_template_pwm_weight_duty_step,
2957 &sensor_dev_template_pwm_max, /* 19 */
2958 &sensor_dev_template_pwm_step, /* 20 */
2959 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2960 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2961 &sensor_dev_template_pwm_auto_point1_temp,
2962 &sensor_dev_template_pwm_auto_point2_pwm,
2963 &sensor_dev_template_pwm_auto_point2_temp,
2964 &sensor_dev_template_pwm_auto_point3_pwm,
2965 &sensor_dev_template_pwm_auto_point3_temp,
2966 &sensor_dev_template_pwm_auto_point4_pwm,
2967 &sensor_dev_template_pwm_auto_point4_temp,
2968 &sensor_dev_template_pwm_auto_point5_pwm,
2969 &sensor_dev_template_pwm_auto_point5_temp,
2970 &sensor_dev_template_pwm_auto_point6_pwm,
2971 &sensor_dev_template_pwm_auto_point6_temp,
2972 &sensor_dev_template_pwm_auto_point7_pwm,
2973 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002974
Guenter Roeckf73cf632013-03-18 09:22:50 -07002975 NULL
2976};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002977
Guenter Roeckf73cf632013-03-18 09:22:50 -07002978static struct sensor_template_group nct6775_pwm_template_group = {
2979 .templates = nct6775_attributes_pwm_template,
2980 .is_visible = nct6775_pwm_is_visible,
2981 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002982};
2983
2984static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002985show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2986{
2987 struct nct6775_data *data = dev_get_drvdata(dev);
2988 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
2989}
2990
2991static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2992
Guenter Roecka6bd5872012-12-04 03:13:34 -08002993/* Case open detection */
2994
2995static ssize_t
2996clear_caseopen(struct device *dev, struct device_attribute *attr,
2997 const char *buf, size_t count)
2998{
2999 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003000 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3001 unsigned long val;
3002 u8 reg;
3003 int ret;
3004
3005 if (kstrtoul(buf, 10, &val) || val != 0)
3006 return -EINVAL;
3007
3008 mutex_lock(&data->update_lock);
3009
3010 /*
3011 * Use CR registers to clear caseopen status.
3012 * The CR registers are the same for all chips, and not all chips
3013 * support clearing the caseopen status through "regular" registers.
3014 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003015 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003016 if (ret) {
3017 count = ret;
3018 goto error;
3019 }
3020
Guenter Roeckdf612d52013-07-08 13:15:04 -07003021 superio_select(data->sioreg, NCT6775_LD_ACPI);
3022 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003023 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003024 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003025 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003026 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3027 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003028
3029 data->valid = false; /* Force cache refresh */
3030error:
3031 mutex_unlock(&data->update_lock);
3032 return count;
3033}
3034
Guenter Roeckf73cf632013-03-18 09:22:50 -07003035static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3036 clear_caseopen, INTRUSION_ALARM_BASE);
3037static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3038 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003039static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3040 store_beep, INTRUSION_ALARM_BASE);
3041static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3042 store_beep, INTRUSION_ALARM_BASE + 1);
3043static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3044 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003045
3046static umode_t nct6775_other_is_visible(struct kobject *kobj,
3047 struct attribute *attr, int index)
3048{
3049 struct device *dev = container_of(kobj, struct device, kobj);
3050 struct nct6775_data *data = dev_get_drvdata(dev);
3051
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003052 if (index == 0 && !data->have_vid)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003053 return 0;
3054
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003055 if (index == 1 || index == 2) {
3056 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003057 return 0;
3058 }
3059
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003060 if (index == 3 || index == 4) {
3061 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
Guenter Roeck30846992013-06-24 22:21:59 -07003062 return 0;
3063 }
3064
Guenter Roeckf73cf632013-03-18 09:22:50 -07003065 return attr->mode;
3066}
3067
3068/*
3069 * nct6775_other_is_visible uses the index into the following array
3070 * to determine if attributes should be created or not.
3071 * Any change in order or content must be matched.
3072 */
3073static struct attribute *nct6775_attributes_other[] = {
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003074 &dev_attr_cpu0_vid.attr, /* 0 */
3075 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
3076 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
3077 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
3078 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
3079 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003080
3081 NULL
3082};
3083
3084static const struct attribute_group nct6775_group_other = {
3085 .attrs = nct6775_attributes_other,
3086 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003087};
3088
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003089static inline void nct6775_init_device(struct nct6775_data *data)
3090{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003091 int i;
3092 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003093
3094 /* Start monitoring if needed */
3095 if (data->REG_CONFIG) {
3096 tmp = nct6775_read_value(data, data->REG_CONFIG);
3097 if (!(tmp & 0x01))
3098 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3099 }
3100
Guenter Roeckaa136e52012-12-04 03:26:05 -08003101 /* Enable temperature sensors if needed */
3102 for (i = 0; i < NUM_TEMP; i++) {
3103 if (!(data->have_temp & (1 << i)))
3104 continue;
3105 if (!data->reg_temp_config[i])
3106 continue;
3107 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3108 if (tmp & 0x01)
3109 nct6775_write_value(data, data->reg_temp_config[i],
3110 tmp & 0xfe);
3111 }
3112
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003113 /* Enable VBAT monitoring if needed */
3114 tmp = nct6775_read_value(data, data->REG_VBAT);
3115 if (!(tmp & 0x01))
3116 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003117
3118 diode = nct6775_read_value(data, data->REG_DIODE);
3119
3120 for (i = 0; i < data->temp_fixed_num; i++) {
3121 if (!(data->have_temp_fixed & (1 << i)))
3122 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003123 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3124 data->temp_type[i]
3125 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003126 else /* thermistor */
3127 data->temp_type[i] = 4;
3128 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003129}
3130
Guenter Roeckf73cf632013-03-18 09:22:50 -07003131static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003132nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003133{
David Bartley578ab5f2013-06-24 22:28:28 -07003134 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3135 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003136 int sioreg = data->sioreg;
3137 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003138
3139 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3140 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003141 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003142
3143 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003144 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003145
3146 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003147 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003148 fan4min = false;
3149 fan5pin = false;
3150 fan6pin = false;
3151 pwm4pin = false;
3152 pwm5pin = false;
3153 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003154 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003155 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003156
Guenter Roeckdf612d52013-07-08 13:15:04 -07003157 superio_select(sioreg, NCT6775_LD_HWM);
3158 regval = superio_inb(sioreg, SIO_REG_ENABLE);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003159
3160 if (regval & 0x80)
3161 fan3pin = gpok;
3162 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003163 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003164
3165 if (regval & 0x40)
3166 fan4pin = gpok;
3167 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003168 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003169
3170 if (regval & 0x20)
3171 fan5pin = gpok;
3172 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003173 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003174
3175 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003176 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003177 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003178 pwm4pin = false;
3179 pwm5pin = false;
3180 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003181 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003182 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003183 fan3pin = !(regval & 0x80);
3184 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003185
3186 fan4pin = false;
3187 fan4min = false;
3188 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003189 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003190 pwm4pin = false;
3191 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003192 pwm6pin = false;
3193 } else { /* NCT6779D or NCT6791D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003194 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003195
3196 fan3pin = !(regval & (1 << 5));
3197 fan4pin = !(regval & (1 << 6));
3198 fan5pin = !(regval & (1 << 7));
3199
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003200 pwm3pin = !(regval & (1 << 0));
3201 pwm4pin = !(regval & (1 << 1));
3202 pwm5pin = !(regval & (1 << 2));
3203
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003204 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003205
3206 if (data->kind == nct6791) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003207 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003208 fan6pin = (regval & (1 << 1));
3209 pwm6pin = (regval & (1 << 0));
3210 } else { /* NCT6779D */
3211 fan6pin = false;
3212 pwm6pin = false;
3213 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003214 }
3215
David Bartley578ab5f2013-06-24 22:28:28 -07003216 /* fan 1 and 2 (0x03) are always present */
3217 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3218 (fan5pin << 4) | (fan6pin << 5);
3219 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3220 (fan5pin << 4);
3221 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3222 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003223}
3224
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003225static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3226 int *available, int *mask)
3227{
3228 int i;
3229 u8 src;
3230
3231 for (i = 0; i < data->pwm_num && *available; i++) {
3232 int index;
3233
3234 if (!regp[i])
3235 continue;
3236 src = nct6775_read_value(data, regp[i]);
3237 src &= 0x1f;
3238 if (!src || (*mask & (1 << src)))
3239 continue;
3240 if (src >= data->temp_label_num ||
3241 !strlen(data->temp_label[src]))
3242 continue;
3243
3244 index = __ffs(*available);
3245 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3246 *available &= ~(1 << index);
3247 *mask |= 1 << src;
3248 }
3249}
3250
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003251static int nct6775_probe(struct platform_device *pdev)
3252{
3253 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003254 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003255 struct nct6775_data *data;
3256 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003257 int i, s, err = 0;
3258 int src, mask, available;
3259 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003260 const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003261 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003262 int num_reg_temp, num_reg_temp_mon;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003263 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003264 struct attribute_group *group;
Guenter Roecka150d952013-07-11 22:55:22 -07003265 struct device *hwmon_dev;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003266
3267 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3268 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3269 DRVNAME))
3270 return -EBUSY;
3271
3272 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3273 GFP_KERNEL);
3274 if (!data)
3275 return -ENOMEM;
3276
3277 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003278 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003279 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003280 mutex_init(&data->update_lock);
3281 data->name = nct6775_device_names[data->kind];
3282 data->bank = 0xff; /* Force initial bank selection */
3283 platform_set_drvdata(pdev, data);
3284
3285 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003286 case nct6106:
3287 data->in_num = 9;
3288 data->pwm_num = 3;
3289 data->auto_pwm_num = 4;
3290 data->temp_fixed_num = 3;
3291 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003292 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003293
3294 data->fan_from_reg = fan_from_reg13;
3295 data->fan_from_reg_min = fan_from_reg13;
3296
3297 data->temp_label = nct6776_temp_label;
3298 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3299
3300 data->REG_VBAT = NCT6106_REG_VBAT;
3301 data->REG_DIODE = NCT6106_REG_DIODE;
3302 data->DIODE_MASK = NCT6106_DIODE_MASK;
3303 data->REG_VIN = NCT6106_REG_IN;
3304 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3305 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3306 data->REG_TARGET = NCT6106_REG_TARGET;
3307 data->REG_FAN = NCT6106_REG_FAN;
3308 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3309 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3310 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3311 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3312 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3313 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3314 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3315 data->REG_PWM[0] = NCT6106_REG_PWM;
3316 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3317 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3318 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3319 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3320 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3321 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3322 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3323 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3324 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3325 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3326 data->REG_CRITICAL_TEMP_TOLERANCE
3327 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3328 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3329 data->CRITICAL_PWM_ENABLE_MASK
3330 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3331 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3332 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3333 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3334 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3335 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3336 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3337 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3338 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3339 data->REG_ALARM = NCT6106_REG_ALARM;
3340 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003341 data->REG_BEEP = NCT6106_REG_BEEP;
3342 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003343
3344 reg_temp = NCT6106_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003345 reg_temp_mon = NCT6106_REG_TEMP_MON;
Guenter Roeck6c009502012-07-01 08:23:15 -07003346 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003347 num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
Guenter Roeck6c009502012-07-01 08:23:15 -07003348 reg_temp_over = NCT6106_REG_TEMP_OVER;
3349 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3350 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3351 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3352 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003353 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3354 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003355
3356 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003357 case nct6775:
3358 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003359 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003360 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003361 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003362 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003363 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003364 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003365
3366 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003367 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003368
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003369 data->fan_from_reg = fan_from_reg16;
3370 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003371 data->target_temp_mask = 0x7f;
3372 data->tolerance_mask = 0x0f;
3373 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003374
Guenter Roeckaa136e52012-12-04 03:26:05 -08003375 data->temp_label = nct6775_temp_label;
3376 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3377
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003378 data->REG_CONFIG = NCT6775_REG_CONFIG;
3379 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003380 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003381 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003382 data->REG_VIN = NCT6775_REG_IN;
3383 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3384 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003385 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003386 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003387 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003388 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003389 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003390 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003391 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3392 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3393 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003394 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003395 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3396 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3397 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3398 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003399 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003400 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3401 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3402 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003403 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3404 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3405 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3406 data->REG_CRITICAL_TEMP_TOLERANCE
3407 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003408 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3409 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003410 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003411 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3412 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3413 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3414 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003415 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003416 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003417
3418 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003419 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003420 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003421 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003422 reg_temp_over = NCT6775_REG_TEMP_OVER;
3423 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3424 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3425 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3426 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3427
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003428 break;
3429 case nct6776:
3430 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003431 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003432 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003433 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003434 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003435 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003436 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003437
3438 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003439 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003440
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003441 data->fan_from_reg = fan_from_reg13;
3442 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003443 data->target_temp_mask = 0xff;
3444 data->tolerance_mask = 0x07;
3445 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003446
Guenter Roeckaa136e52012-12-04 03:26:05 -08003447 data->temp_label = nct6776_temp_label;
3448 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3449
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003450 data->REG_CONFIG = NCT6775_REG_CONFIG;
3451 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003452 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003453 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003454 data->REG_VIN = NCT6775_REG_IN;
3455 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3456 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003457 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003458 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003459 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003460 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003461 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003462 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003463 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3464 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3465 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3466 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003467 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003468 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3469 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003470 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3471 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003472 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3473 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3474 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003475 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3476 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3477 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3478 data->REG_CRITICAL_TEMP_TOLERANCE
3479 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003480 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3481 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003482 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003483 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3484 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3485 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3486 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003487 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003488 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003489
3490 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003491 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003492 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003493 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003494 reg_temp_over = NCT6775_REG_TEMP_OVER;
3495 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3496 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3497 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3498 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3499
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003500 break;
3501 case nct6779:
3502 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003503 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003504 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003505 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003506 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003507 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003508 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003509
3510 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003511 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003512
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003513 data->fan_from_reg = fan_from_reg13;
3514 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003515 data->target_temp_mask = 0xff;
3516 data->tolerance_mask = 0x07;
3517 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003518
Guenter Roeckaa136e52012-12-04 03:26:05 -08003519 data->temp_label = nct6779_temp_label;
3520 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3521
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003522 data->REG_CONFIG = NCT6775_REG_CONFIG;
3523 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003524 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003525 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003526 data->REG_VIN = NCT6779_REG_IN;
3527 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3528 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003529 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003530 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003531 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003532 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003533 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003534 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003535 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3536 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3537 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3538 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003539 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003540 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3541 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003542 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3543 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003544 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3545 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3546 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003547 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3548 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3549 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3550 data->REG_CRITICAL_TEMP_TOLERANCE
3551 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003552 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3553 data->CRITICAL_PWM_ENABLE_MASK
3554 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3555 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003556 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3557 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003558 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003559 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3560 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3561 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3562 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003563 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003564 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003565
3566 reg_temp = NCT6779_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003567 reg_temp_mon = NCT6779_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003568 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003569 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003570 reg_temp_over = NCT6779_REG_TEMP_OVER;
3571 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3572 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3573 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3574 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3575
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003576 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003577 case nct6791:
3578 data->in_num = 15;
3579 data->pwm_num = 6;
3580 data->auto_pwm_num = 4;
3581 data->has_fan_div = false;
3582 data->temp_fixed_num = 6;
3583 data->num_temp_alarms = 2;
3584 data->num_temp_beeps = 2;
3585
3586 data->ALARM_BITS = NCT6791_ALARM_BITS;
3587 data->BEEP_BITS = NCT6779_BEEP_BITS;
3588
3589 data->fan_from_reg = fan_from_reg13;
3590 data->fan_from_reg_min = fan_from_reg13;
3591 data->target_temp_mask = 0xff;
3592 data->tolerance_mask = 0x07;
3593 data->speed_tolerance_limit = 63;
3594
3595 data->temp_label = nct6779_temp_label;
3596 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3597
3598 data->REG_CONFIG = NCT6775_REG_CONFIG;
3599 data->REG_VBAT = NCT6775_REG_VBAT;
3600 data->REG_DIODE = NCT6775_REG_DIODE;
3601 data->DIODE_MASK = NCT6775_DIODE_MASK;
3602 data->REG_VIN = NCT6779_REG_IN;
3603 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3604 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3605 data->REG_TARGET = NCT6775_REG_TARGET;
3606 data->REG_FAN = NCT6779_REG_FAN;
3607 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3608 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3609 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3610 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3611 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3612 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3613 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3614 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3615 data->REG_PWM[0] = NCT6775_REG_PWM;
3616 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3617 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3618 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3619 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3620 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3621 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3622 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3623 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3624 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3625 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3626 data->REG_CRITICAL_TEMP_TOLERANCE
3627 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3628 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3629 data->CRITICAL_PWM_ENABLE_MASK
3630 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3631 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3632 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3633 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3634 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3635 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3636 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3637 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3638 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3639 data->REG_ALARM = NCT6791_REG_ALARM;
3640 data->REG_BEEP = NCT6776_REG_BEEP;
3641
3642 reg_temp = NCT6779_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003643 reg_temp_mon = NCT6779_REG_TEMP_MON;
David Bartley578ab5f2013-06-24 22:28:28 -07003644 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003645 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
David Bartley578ab5f2013-06-24 22:28:28 -07003646 reg_temp_over = NCT6779_REG_TEMP_OVER;
3647 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3648 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3649 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3650 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3651
3652 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003653 default:
3654 return -ENODEV;
3655 }
3656 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003657 data->have_temp = 0;
3658
3659 /*
3660 * On some boards, not all available temperature sources are monitored,
3661 * even though some of the monitoring registers are unused.
3662 * Get list of unused monitoring registers, then detect if any fan
3663 * controls are configured to use unmonitored temperature sources.
3664 * If so, assign the unmonitored temperature sources to available
3665 * monitoring registers.
3666 */
3667 mask = 0;
3668 available = 0;
3669 for (i = 0; i < num_reg_temp; i++) {
3670 if (reg_temp[i] == 0)
3671 continue;
3672
3673 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3674 if (!src || (mask & (1 << src)))
3675 available |= 1 << i;
3676
3677 mask |= 1 << src;
3678 }
3679
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003680 /*
3681 * Now find unmonitored temperature registers and enable monitoring
3682 * if additional monitoring registers are available.
3683 */
3684 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3685 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3686
Guenter Roeckaa136e52012-12-04 03:26:05 -08003687 mask = 0;
3688 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3689 for (i = 0; i < num_reg_temp; i++) {
3690 if (reg_temp[i] == 0)
3691 continue;
3692
3693 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3694 if (!src || (mask & (1 << src)))
3695 continue;
3696
3697 if (src >= data->temp_label_num ||
3698 !strlen(data->temp_label[src])) {
3699 dev_info(dev,
3700 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3701 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3702 continue;
3703 }
3704
3705 mask |= 1 << src;
3706
3707 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3708 if (src <= data->temp_fixed_num) {
3709 data->have_temp |= 1 << (src - 1);
3710 data->have_temp_fixed |= 1 << (src - 1);
3711 data->reg_temp[0][src - 1] = reg_temp[i];
3712 data->reg_temp[1][src - 1] = reg_temp_over[i];
3713 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003714 if (reg_temp_crit_h && reg_temp_crit_h[i])
3715 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3716 else if (reg_temp_crit[src - 1])
3717 data->reg_temp[3][src - 1]
3718 = reg_temp_crit[src - 1];
3719 if (reg_temp_crit_l && reg_temp_crit_l[i])
3720 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003721 data->reg_temp_config[src - 1] = reg_temp_config[i];
3722 data->temp_src[src - 1] = src;
3723 continue;
3724 }
3725
3726 if (s >= NUM_TEMP)
3727 continue;
3728
3729 /* Use dynamic index for other sources */
3730 data->have_temp |= 1 << s;
3731 data->reg_temp[0][s] = reg_temp[i];
3732 data->reg_temp[1][s] = reg_temp_over[i];
3733 data->reg_temp[2][s] = reg_temp_hyst[i];
3734 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003735 if (reg_temp_crit_h && reg_temp_crit_h[i])
3736 data->reg_temp[3][s] = reg_temp_crit_h[i];
3737 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003738 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003739 if (reg_temp_crit_l && reg_temp_crit_l[i])
3740 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003741
3742 data->temp_src[s] = src;
3743 s++;
3744 }
3745
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003746 /*
3747 * Repeat with temperatures used for fan control.
3748 * This set of registers does not support limits.
3749 */
3750 for (i = 0; i < num_reg_temp_mon; i++) {
3751 if (reg_temp_mon[i] == 0)
3752 continue;
3753
3754 src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f;
3755 if (!src || (mask & (1 << src)))
3756 continue;
3757
3758 if (src >= data->temp_label_num ||
3759 !strlen(data->temp_label[src])) {
3760 dev_info(dev,
3761 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3762 src, i, data->REG_TEMP_SEL[i],
3763 reg_temp_mon[i]);
3764 continue;
3765 }
3766
3767 mask |= 1 << src;
3768
3769 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3770 if (src <= data->temp_fixed_num) {
3771 if (data->have_temp & (1 << (src - 1)))
3772 continue;
3773 data->have_temp |= 1 << (src - 1);
3774 data->have_temp_fixed |= 1 << (src - 1);
3775 data->reg_temp[0][src - 1] = reg_temp_mon[i];
3776 data->temp_src[src - 1] = src;
3777 continue;
3778 }
3779
3780 if (s >= NUM_TEMP)
3781 continue;
3782
3783 /* Use dynamic index for other sources */
3784 data->have_temp |= 1 << s;
3785 data->reg_temp[0][s] = reg_temp_mon[i];
3786 data->temp_src[s] = src;
3787 s++;
3788 }
3789
Guenter Roeckaa136e52012-12-04 03:26:05 -08003790#ifdef USE_ALTERNATE
3791 /*
3792 * Go through the list of alternate temp registers and enable
3793 * if possible.
3794 * The temperature is already monitored if the respective bit in <mask>
3795 * is set.
3796 */
3797 for (i = 0; i < data->temp_label_num - 1; i++) {
3798 if (!reg_temp_alternate[i])
3799 continue;
3800 if (mask & (1 << (i + 1)))
3801 continue;
3802 if (i < data->temp_fixed_num) {
3803 if (data->have_temp & (1 << i))
3804 continue;
3805 data->have_temp |= 1 << i;
3806 data->have_temp_fixed |= 1 << i;
3807 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003808 if (i < num_reg_temp) {
3809 data->reg_temp[1][i] = reg_temp_over[i];
3810 data->reg_temp[2][i] = reg_temp_hyst[i];
3811 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003812 data->temp_src[i] = i + 1;
3813 continue;
3814 }
3815
3816 if (s >= NUM_TEMP) /* Abort if no more space */
3817 break;
3818
3819 data->have_temp |= 1 << s;
3820 data->reg_temp[0][s] = reg_temp_alternate[i];
3821 data->temp_src[s] = i + 1;
3822 s++;
3823 }
3824#endif /* USE_ALTERNATE */
3825
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003826 /* Initialize the chip */
3827 nct6775_init_device(data);
3828
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003829 err = superio_enter(sio_data->sioreg);
3830 if (err)
3831 return err;
3832
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003833 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3834 switch (data->kind) {
3835 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003836 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003837 break;
3838 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003839 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003840 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003841 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003842 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003843 case nct6791:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003844 break;
3845 }
3846
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003847 /*
3848 * Read VID value
3849 * We can get the VID input values directly at logical device D 0xe3.
3850 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003851 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003852 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3853 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3854 data->vrm = vid_which_vrm();
3855 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003856
3857 if (fan_debounce) {
3858 u8 tmp;
3859
3860 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3861 tmp = superio_inb(sio_data->sioreg,
3862 NCT6775_REG_CR_FAN_DEBOUNCE);
3863 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003864 case nct6106:
3865 tmp |= 0xe0;
3866 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003867 case nct6775:
3868 tmp |= 0x1e;
3869 break;
3870 case nct6776:
3871 case nct6779:
3872 tmp |= 0x3e;
3873 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003874 case nct6791:
3875 tmp |= 0x7e;
3876 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003877 }
3878 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3879 tmp);
3880 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3881 data->name);
3882 }
3883
Guenter Roeckdf612d52013-07-08 13:15:04 -07003884 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003885
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003886 superio_exit(sio_data->sioreg);
3887
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003888 /* Read fan clock dividers immediately */
3889 nct6775_init_fan_common(dev, data);
3890
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003891 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003892 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3893 data->pwm_num);
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003894 if (IS_ERR(group))
3895 return PTR_ERR(group);
3896
3897 data->groups[data->num_attr_groups++] = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003898
Guenter Roeckf73cf632013-03-18 09:22:50 -07003899 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3900 fls(data->have_in));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003901 if (IS_ERR(group))
3902 return PTR_ERR(group);
3903
3904 data->groups[data->num_attr_groups++] = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003905
Guenter Roeckf73cf632013-03-18 09:22:50 -07003906 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3907 fls(data->has_fan));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003908 if (IS_ERR(group))
3909 return PTR_ERR(group);
3910
3911 data->groups[data->num_attr_groups++] = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003912
Guenter Roeckf73cf632013-03-18 09:22:50 -07003913 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3914 fls(data->have_temp));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003915 if (IS_ERR(group))
3916 return PTR_ERR(group);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003917
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003918 data->groups[data->num_attr_groups++] = group;
3919 data->groups[data->num_attr_groups++] = &nct6775_group_other;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003920
Guenter Roecka150d952013-07-11 22:55:22 -07003921 hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
3922 data, data->groups);
Fengguang Wu9c09bd82013-09-17 06:43:42 -07003923 return PTR_ERR_OR_ZERO(hwmon_dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003924}
3925
Guenter Roeck84d19d92012-12-04 08:01:39 -08003926#ifdef CONFIG_PM
3927static int nct6775_suspend(struct device *dev)
3928{
3929 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003930
3931 mutex_lock(&data->update_lock);
3932 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003933 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003934 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3935 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3936 }
3937 mutex_unlock(&data->update_lock);
3938
3939 return 0;
3940}
3941
3942static int nct6775_resume(struct device *dev)
3943{
3944 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003945 int i, j;
3946
3947 mutex_lock(&data->update_lock);
3948 data->bank = 0xff; /* Force initial bank selection */
3949
3950 /* Restore limits */
3951 for (i = 0; i < data->in_num; i++) {
3952 if (!(data->have_in & (1 << i)))
3953 continue;
3954
3955 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3956 data->in[i][1]);
3957 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3958 data->in[i][2]);
3959 }
3960
Guenter Roeckc409fd42013-04-09 05:04:00 -07003961 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003962 if (!(data->has_fan_min & (1 << i)))
3963 continue;
3964
3965 nct6775_write_value(data, data->REG_FAN_MIN[i],
3966 data->fan_min[i]);
3967 }
3968
3969 for (i = 0; i < NUM_TEMP; i++) {
3970 if (!(data->have_temp & (1 << i)))
3971 continue;
3972
Guenter Roeckc409fd42013-04-09 05:04:00 -07003973 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003974 if (data->reg_temp[j][i])
3975 nct6775_write_temp(data, data->reg_temp[j][i],
3976 data->temp[j][i]);
3977 }
3978
3979 /* Restore other settings */
3980 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003981 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003982 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3983 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3984 }
3985
3986 /* Force re-reading all values */
3987 data->valid = false;
3988 mutex_unlock(&data->update_lock);
3989
3990 return 0;
3991}
3992
3993static const struct dev_pm_ops nct6775_dev_pm_ops = {
3994 .suspend = nct6775_suspend,
3995 .resume = nct6775_resume,
Harald Judt374d1f92013-07-30 19:50:16 +02003996 .freeze = nct6775_suspend,
3997 .restore = nct6775_resume,
Guenter Roeck84d19d92012-12-04 08:01:39 -08003998};
3999
4000#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4001#else
4002#define NCT6775_DEV_PM_OPS NULL
4003#endif /* CONFIG_PM */
4004
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004005static struct platform_driver nct6775_driver = {
4006 .driver = {
4007 .owner = THIS_MODULE,
4008 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004009 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004010 },
4011 .probe = nct6775_probe,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004012};
4013
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004014static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07004015 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004016 "NCT6775F",
4017 "NCT6776D/F",
4018 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07004019 "NCT6791D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004020};
4021
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004022/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004023static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004024{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004025 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004026 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004027 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004028
4029 err = superio_enter(sioaddr);
4030 if (err)
4031 return err;
4032
4033 if (force_id)
4034 val = force_id;
4035 else
4036 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4037 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4038 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07004039 case SIO_NCT6106_ID:
4040 sio_data->kind = nct6106;
4041 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004042 case SIO_NCT6775_ID:
4043 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004044 break;
4045 case SIO_NCT6776_ID:
4046 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004047 break;
4048 case SIO_NCT6779_ID:
4049 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004050 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004051 case SIO_NCT6791_ID:
4052 sio_data->kind = nct6791;
4053 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004054 default:
4055 if (val != 0xffff)
4056 pr_debug("unsupported chip ID: 0x%04x\n", val);
4057 superio_exit(sioaddr);
4058 return -ENODEV;
4059 }
4060
4061 /* We have a known chip, find the HWM I/O address */
4062 superio_select(sioaddr, NCT6775_LD_HWM);
4063 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4064 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004065 addr = val & IOREGION_ALIGNMENT;
4066 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004067 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4068 superio_exit(sioaddr);
4069 return -ENODEV;
4070 }
4071
4072 /* Activate logical device if needed */
4073 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4074 if (!(val & 0x01)) {
4075 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4076 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4077 }
David Bartley578ab5f2013-06-24 22:28:28 -07004078 if (sio_data->kind == nct6791) {
4079 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
4080 if (val & 0x10) {
4081 pr_info("Enabling hardware monitor logical device mappings.\n");
4082 superio_outb(sioaddr,
4083 NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
4084 val & ~0x10);
4085 }
4086 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004087
4088 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004089 pr_info("Found %s or compatible chip at %#x:%#x\n",
4090 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004091 sio_data->sioreg = sioaddr;
4092
Guenter Roeck698a7c22013-04-05 07:35:25 -07004093 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004094}
4095
4096/*
4097 * when Super-I/O functions move to a separate file, the Super-I/O
4098 * bus will manage the lifetime of the device and this module will only keep
Guenter Roeck615fc8c2013-07-06 09:43:30 -07004099 * track of the nct6775 driver. But since we use platform_device_alloc(), we
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004100 * must keep track of the device
4101 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004102static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004103
4104static int __init sensors_nct6775_init(void)
4105{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004106 int i, err;
4107 bool found = false;
4108 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004109 struct resource res;
4110 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004111 int sioaddr[2] = { 0x2e, 0x4e };
4112
4113 err = platform_driver_register(&nct6775_driver);
4114 if (err)
4115 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004116
4117 /*
4118 * initialize sio_data->kind and sio_data->sioreg.
4119 *
4120 * when Super-I/O functions move to a separate file, the Super-I/O
4121 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4122 * nct6775 hardware monitor, and call probe()
4123 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004124 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4125 address = nct6775_find(sioaddr[i], &sio_data);
4126 if (address <= 0)
4127 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004128
Guenter Roeck698a7c22013-04-05 07:35:25 -07004129 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004130
Guenter Roeck698a7c22013-04-05 07:35:25 -07004131 pdev[i] = platform_device_alloc(DRVNAME, address);
4132 if (!pdev[i]) {
4133 err = -ENOMEM;
4134 goto exit_device_put;
4135 }
4136
4137 err = platform_device_add_data(pdev[i], &sio_data,
4138 sizeof(struct nct6775_sio_data));
4139 if (err)
4140 goto exit_device_put;
4141
4142 memset(&res, 0, sizeof(res));
4143 res.name = DRVNAME;
4144 res.start = address + IOREGION_OFFSET;
4145 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4146 res.flags = IORESOURCE_IO;
4147
4148 err = acpi_check_resource_conflict(&res);
4149 if (err) {
4150 platform_device_put(pdev[i]);
4151 pdev[i] = NULL;
4152 continue;
4153 }
4154
4155 err = platform_device_add_resources(pdev[i], &res, 1);
4156 if (err)
4157 goto exit_device_put;
4158
4159 /* platform_device_add calls probe() */
4160 err = platform_device_add(pdev[i]);
4161 if (err)
4162 goto exit_device_put;
4163 }
4164 if (!found) {
4165 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004166 goto exit_unregister;
4167 }
4168
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004169 return 0;
4170
4171exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07004172 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4173 if (pdev[i])
4174 platform_device_put(pdev[i]);
4175 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004176exit_unregister:
4177 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004178 return err;
4179}
4180
4181static void __exit sensors_nct6775_exit(void)
4182{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004183 int i;
4184
4185 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4186 if (pdev[i])
4187 platform_device_unregister(pdev[i]);
4188 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004189 platform_driver_unregister(&nct6775_driver);
4190}
4191
4192MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4193MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4194MODULE_LICENSE("GPL");
4195
4196module_init(sensors_nct6775_init);
4197module_exit(sensors_nct6775_exit);