blob: 504cbddbdd900336703506e55d0455cd6afc307d [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
Jean Delvare7c81c602014-01-29 20:40:08 +01008 * Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de>
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07009 * 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
Guenter Roeckcc76dee2013-11-13 12:47:17 -0800513static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[6] = { 0, 0x239 };
514static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[6] = { 0, 0x23a };
515static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[6] = { 0, 0x23b };
516static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[6] = { 0, 0x23c };
517static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[6] = { 0, 0x23d };
518static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[6] = { 0, 0x23e };
519
David Bartley578ab5f2013-06-24 22:28:28 -0700520static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
521 0x459, 0x45A, 0x45B, 0x568, 0x45D };
522
523static const s8 NCT6791_ALARM_BITS[] = {
524 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
525 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
526 -1, /* unused */
527 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
528 -1, -1, /* unused */
529 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
530 12, 9 }; /* intrusion0, intrusion1 */
531
532
Guenter Roeck6c009502012-07-01 08:23:15 -0700533/* NCT6102D/NCT6106D specific data */
534
535#define NCT6106_REG_VBAT 0x318
536#define NCT6106_REG_DIODE 0x319
537#define NCT6106_DIODE_MASK 0x01
538
539static const u16 NCT6106_REG_IN_MAX[] = {
540 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
541static const u16 NCT6106_REG_IN_MIN[] = {
542 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
543static const u16 NCT6106_REG_IN[] = {
544 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
545
546static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
Guenter Roeckd1a284b2013-11-13 12:46:20 -0800547static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
Guenter Roeck6c009502012-07-01 08:23:15 -0700548static const u16 NCT6106_REG_TEMP_HYST[] = {
549 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
550static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700551 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
552static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
553 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
554static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
555 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700556static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
557static const u16 NCT6106_REG_TEMP_CONFIG[] = {
558 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
559
560static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
561static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
562static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
563static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
564
565static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
566static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
567static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
568static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
569static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
570static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
571static const u16 NCT6106_REG_TEMP_SOURCE[] = {
572 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
573
574static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
575static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
576 0x11b, 0x12b, 0x13b };
577
578static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
579#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
580static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
581
582static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
583static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
584static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
585static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
586static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
587static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
588
589static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
590
591static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
592static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
593static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
594static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
595static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
596static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
597
598static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
599static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
600
601static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
602 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
603
604static const s8 NCT6106_ALARM_BITS[] = {
605 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
606 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
607 -1, /* unused */
608 32, 33, 34, -1, -1, /* fan1..fan5 */
609 -1, -1, -1, /* unused */
610 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
611 48, -1 /* intrusion0, intrusion1 */
612};
613
Guenter Roeck30846992013-06-24 22:21:59 -0700614static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
615 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
616
617static const s8 NCT6106_BEEP_BITS[] = {
618 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
619 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
620 32, /* global beep enable */
621 24, 25, 26, 27, 28, /* fan1..fan5 */
622 -1, -1, -1, /* unused */
623 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
624 34, -1 /* intrusion0, intrusion1 */
625};
626
Guenter Roeck6c009502012-07-01 08:23:15 -0700627static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
628 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
629
630static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
631 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
632
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800633static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
634{
635 if (mode == 0 && pwm == 255)
636 return off;
637 return mode + 1;
638}
639
640static int pwm_enable_to_reg(enum pwm_enable mode)
641{
642 if (mode == off)
643 return 0;
644 return mode - 1;
645}
646
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700647/*
648 * Conversions
649 */
650
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800651/* 1 is DC mode, output in ms */
652static unsigned int step_time_from_reg(u8 reg, u8 mode)
653{
654 return mode ? 400 * reg : 100 * reg;
655}
656
657static u8 step_time_to_reg(unsigned int msec, u8 mode)
658{
659 return clamp_val((mode ? (msec + 200) / 400 :
660 (msec + 50) / 100), 1, 255);
661}
662
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800663static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
664{
665 if (reg == 0 || reg == 255)
666 return 0;
667 return 1350000U / (reg << divreg);
668}
669
670static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
671{
672 if ((reg & 0xff1f) == 0xff1f)
673 return 0;
674
675 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
676
677 if (reg == 0)
678 return 0;
679
680 return 1350000U / reg;
681}
682
683static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
684{
685 if (reg == 0 || reg == 0xffff)
686 return 0;
687
688 /*
689 * Even though the registers are 16 bit wide, the fan divisor
690 * still applies.
691 */
692 return 1350000U / (reg << divreg);
693}
694
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800695static u16 fan_to_reg(u32 fan, unsigned int divreg)
696{
697 if (!fan)
698 return 0;
699
700 return (1350000U / fan) >> divreg;
701}
702
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800703static inline unsigned int
704div_from_reg(u8 reg)
705{
706 return 1 << reg;
707}
708
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700709/*
710 * Some of the voltage inputs have internal scaling, the tables below
711 * contain 8 (the ADC LSB in mV) * scaling factor * 100
712 */
713static const u16 scale_in[15] = {
714 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
715 800, 800
716};
717
718static inline long in_from_reg(u8 reg, u8 nr)
719{
720 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
721}
722
723static inline u8 in_to_reg(u32 val, u8 nr)
724{
725 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
726}
727
728/*
729 * Data structures and manipulation thereof
730 */
731
732struct nct6775_data {
733 int addr; /* IO base of hw monitor block */
Guenter Roeckdf612d52013-07-08 13:15:04 -0700734 int sioreg; /* SIO register address */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700735 enum kinds kind;
736 const char *name;
737
Guenter Roeck615fc8c2013-07-06 09:43:30 -0700738 const struct attribute_group *groups[6];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700739
Guenter Roeckb7a61352013-04-02 22:14:06 -0700740 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
741 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800742 */
743 u8 temp_src[NUM_TEMP];
744 u16 reg_temp_config[NUM_TEMP];
745 const char * const *temp_label;
746 int temp_label_num;
747
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700748 u16 REG_CONFIG;
749 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800750 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700751 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700752
753 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700754 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700755
756 const u16 *REG_VIN;
757 const u16 *REG_IN_MINMAX[2];
758
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800759 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800760 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800761 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800762 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800763 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700764 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800765 const u16 *REG_FAN_TIME[3];
766
767 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800768
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800769 const u8 *REG_PWM_MODE;
770 const u8 *PWM_MODE_MASK;
771
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800772 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
773 * [3]=pwm_max, [4]=pwm_step,
774 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800775 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800776 const u16 *REG_PWM_READ;
777
Guenter Roeck6c009502012-07-01 08:23:15 -0700778 const u16 *REG_CRITICAL_PWM_ENABLE;
779 u8 CRITICAL_PWM_ENABLE_MASK;
780 const u16 *REG_CRITICAL_PWM;
781
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800782 const u16 *REG_AUTO_TEMP;
783 const u16 *REG_AUTO_PWM;
784
785 const u16 *REG_CRITICAL_TEMP;
786 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
787
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800788 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800789 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800790 const u16 *REG_WEIGHT_TEMP_SEL;
791 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
792
Guenter Roeckaa136e52012-12-04 03:26:05 -0800793 const u16 *REG_TEMP_OFFSET;
794
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700795 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700796 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700797
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800798 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
799 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
800
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700801 struct mutex update_lock;
802 bool valid; /* true if following fields are valid */
803 unsigned long last_updated; /* In jiffies */
804
805 /* Register values */
806 u8 bank; /* current register bank */
807 u8 in_num; /* number of in inputs we have */
808 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
David Bartley578ab5f2013-06-24 22:28:28 -0700809 unsigned int rpm[NUM_FAN];
810 u16 fan_min[NUM_FAN];
811 u8 fan_pulses[NUM_FAN];
812 u8 fan_div[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800813 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800814 u8 has_fan; /* some fan inputs can be disabled */
815 u8 has_fan_min; /* some fans don't have min register */
816 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700817
Guenter Roeck6c009502012-07-01 08:23:15 -0700818 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700819 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800820 u8 temp_fixed_num; /* 3 or 6 */
821 u8 temp_type[NUM_TEMP_FIXED];
822 s8 temp_offset[NUM_TEMP_FIXED];
Dan Carpenterf58876a2013-07-18 18:01:11 +0300823 s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
824 * 3=temp_crit, 4=temp_lcrit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700825 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700826 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700827
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800828 u8 pwm_num; /* number of pwm */
David Bartley578ab5f2013-06-24 22:28:28 -0700829 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
830 * 0->PWM variable duty cycle
831 */
832 enum pwm_enable pwm_enable[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800833 /* 0->off
834 * 1->manual
835 * 2->thermal cruise mode (also called SmartFan I)
836 * 3->fan speed cruise mode
837 * 4->SmartFan III
838 * 5->enhanced variable thermal cruise (SmartFan IV)
839 */
David Bartley578ab5f2013-06-24 22:28:28 -0700840 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
841 * [3]=pwm_max, [4]=pwm_step,
842 * [5]=weight_duty_step, [6]=weight_duty_base
843 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800844
David Bartley578ab5f2013-06-24 22:28:28 -0700845 u8 target_temp[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800846 u8 target_temp_mask;
David Bartley578ab5f2013-06-24 22:28:28 -0700847 u32 target_speed[NUM_FAN];
848 u32 target_speed_tolerance[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800849 u8 speed_tolerance_limit;
850
David Bartley578ab5f2013-06-24 22:28:28 -0700851 u8 temp_tolerance[2][NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800852 u8 tolerance_mask;
853
David Bartley578ab5f2013-06-24 22:28:28 -0700854 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800855
856 /* Automatic fan speed control registers */
857 int auto_pwm_num;
David Bartley578ab5f2013-06-24 22:28:28 -0700858 u8 auto_pwm[NUM_FAN][7];
859 u8 auto_temp[NUM_FAN][7];
860 u8 pwm_temp_sel[NUM_FAN];
861 u8 pwm_weight_temp_sel[NUM_FAN];
862 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
863 * 2->temp_base
864 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800865
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700866 u8 vid;
867 u8 vrm;
868
Guenter Roeckf73cf632013-03-18 09:22:50 -0700869 bool have_vid;
870
Guenter Roeckaa136e52012-12-04 03:26:05 -0800871 u16 have_temp;
872 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700873 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800874#ifdef CONFIG_PM
875 /* Remember extra register values over suspend/resume */
876 u8 vbat;
877 u8 fandiv1;
878 u8 fandiv2;
879#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700880};
881
882struct nct6775_sio_data {
883 int sioreg;
884 enum kinds kind;
885};
886
Guenter Roeckf73cf632013-03-18 09:22:50 -0700887struct sensor_device_template {
888 struct device_attribute dev_attr;
889 union {
890 struct {
891 u8 nr;
892 u8 index;
893 } s;
894 int index;
895 } u;
896 bool s2; /* true if both index and nr are used */
897};
898
899struct sensor_device_attr_u {
900 union {
901 struct sensor_device_attribute a1;
902 struct sensor_device_attribute_2 a2;
903 } u;
904 char name[32];
905};
906
907#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
908 .attr = {.name = _template, .mode = _mode }, \
909 .show = _show, \
910 .store = _store, \
911}
912
913#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
914 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
915 .u.index = _index, \
916 .s2 = false }
917
918#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
919 _nr, _index) \
920 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
921 .u.s.index = _index, \
922 .u.s.nr = _nr, \
923 .s2 = true }
924
925#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
926static struct sensor_device_template sensor_dev_template_##_name \
927 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
928 _index)
929
930#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
931 _nr, _index) \
932static struct sensor_device_template sensor_dev_template_##_name \
933 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
934 _nr, _index)
935
936struct sensor_template_group {
937 struct sensor_device_template **templates;
938 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
939 int base;
940};
941
942static struct attribute_group *
943nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
944 int repeat)
945{
946 struct attribute_group *group;
947 struct sensor_device_attr_u *su;
948 struct sensor_device_attribute *a;
949 struct sensor_device_attribute_2 *a2;
950 struct attribute **attrs;
951 struct sensor_device_template **t;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300952 int i, count;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700953
954 if (repeat <= 0)
955 return ERR_PTR(-EINVAL);
956
957 t = tg->templates;
958 for (count = 0; *t; t++, count++)
959 ;
960
961 if (count == 0)
962 return ERR_PTR(-EINVAL);
963
964 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
965 if (group == NULL)
966 return ERR_PTR(-ENOMEM);
967
968 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
969 GFP_KERNEL);
970 if (attrs == NULL)
971 return ERR_PTR(-ENOMEM);
972
973 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
974 GFP_KERNEL);
975 if (su == NULL)
976 return ERR_PTR(-ENOMEM);
977
978 group->attrs = attrs;
979 group->is_visible = tg->is_visible;
980
981 for (i = 0; i < repeat; i++) {
982 t = tg->templates;
Dan Carpenter1e687e82013-10-19 11:55:15 +0300983 while (*t != NULL) {
Guenter Roeckf73cf632013-03-18 09:22:50 -0700984 snprintf(su->name, sizeof(su->name),
985 (*t)->dev_attr.attr.name, tg->base + i);
986 if ((*t)->s2) {
987 a2 = &su->u.a2;
988 a2->dev_attr.attr.name = su->name;
989 a2->nr = (*t)->u.s.nr + i;
990 a2->index = (*t)->u.s.index;
991 a2->dev_attr.attr.mode =
992 (*t)->dev_attr.attr.mode;
993 a2->dev_attr.show = (*t)->dev_attr.show;
994 a2->dev_attr.store = (*t)->dev_attr.store;
995 *attrs = &a2->dev_attr.attr;
996 } else {
997 a = &su->u.a1;
998 a->dev_attr.attr.name = su->name;
999 a->index = (*t)->u.index + i;
1000 a->dev_attr.attr.mode =
1001 (*t)->dev_attr.attr.mode;
1002 a->dev_attr.show = (*t)->dev_attr.show;
1003 a->dev_attr.store = (*t)->dev_attr.store;
1004 *attrs = &a->dev_attr.attr;
1005 }
1006 attrs++;
1007 su++;
1008 t++;
1009 }
1010 }
1011
Guenter Roeckf73cf632013-03-18 09:22:50 -07001012 return group;
1013}
1014
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001015static bool is_word_sized(struct nct6775_data *data, u16 reg)
1016{
1017 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07001018 case nct6106:
1019 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1020 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1021 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001022 case nct6775:
1023 return (((reg & 0xff00) == 0x100 ||
1024 (reg & 0xff00) == 0x200) &&
1025 ((reg & 0x00ff) == 0x50 ||
1026 (reg & 0x00ff) == 0x53 ||
1027 (reg & 0x00ff) == 0x55)) ||
1028 (reg & 0xfff0) == 0x630 ||
1029 reg == 0x640 || reg == 0x642 ||
1030 reg == 0x662 ||
1031 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1032 reg == 0x73 || reg == 0x75 || reg == 0x77;
1033 case nct6776:
1034 return (((reg & 0xff00) == 0x100 ||
1035 (reg & 0xff00) == 0x200) &&
1036 ((reg & 0x00ff) == 0x50 ||
1037 (reg & 0x00ff) == 0x53 ||
1038 (reg & 0x00ff) == 0x55)) ||
1039 (reg & 0xfff0) == 0x630 ||
1040 reg == 0x402 ||
1041 reg == 0x640 || reg == 0x642 ||
1042 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1043 reg == 0x73 || reg == 0x75 || reg == 0x77;
1044 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001045 case nct6791:
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001046 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
David Bartley578ab5f2013-06-24 22:28:28 -07001047 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001048 reg == 0x402 ||
1049 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1050 reg == 0x640 || reg == 0x642 ||
1051 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
1052 reg == 0x7b;
1053 }
1054 return false;
1055}
1056
1057/*
1058 * On older chips, only registers 0x50-0x5f are banked.
1059 * On more recent chips, all registers are banked.
1060 * Assume that is the case and set the bank number for each access.
1061 * Cache the bank number so it only needs to be set if it changes.
1062 */
1063static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1064{
1065 u8 bank = reg >> 8;
1066 if (data->bank != bank) {
1067 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1068 outb_p(bank, data->addr + DATA_REG_OFFSET);
1069 data->bank = bank;
1070 }
1071}
1072
1073static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1074{
1075 int res, word_sized = is_word_sized(data, reg);
1076
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001077 nct6775_set_bank(data, reg);
1078 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1079 res = inb_p(data->addr + DATA_REG_OFFSET);
1080 if (word_sized) {
1081 outb_p((reg & 0xff) + 1,
1082 data->addr + ADDR_REG_OFFSET);
1083 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1084 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001085 return res;
1086}
1087
1088static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1089{
1090 int word_sized = is_word_sized(data, reg);
1091
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001092 nct6775_set_bank(data, reg);
1093 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1094 if (word_sized) {
1095 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1096 outb_p((reg & 0xff) + 1,
1097 data->addr + ADDR_REG_OFFSET);
1098 }
1099 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001100 return 0;
1101}
1102
Guenter Roeckaa136e52012-12-04 03:26:05 -08001103/* We left-align 8-bit temperature values to make the code simpler */
1104static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1105{
1106 u16 res;
1107
1108 res = nct6775_read_value(data, reg);
1109 if (!is_word_sized(data, reg))
1110 res <<= 8;
1111
1112 return res;
1113}
1114
1115static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1116{
1117 if (!is_word_sized(data, reg))
1118 value >>= 8;
1119 return nct6775_write_value(data, reg, value);
1120}
1121
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001122/* This function assumes that the caller holds data->update_lock */
1123static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1124{
1125 u8 reg;
1126
1127 switch (nr) {
1128 case 0:
1129 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1130 | (data->fan_div[0] & 0x7);
1131 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1132 break;
1133 case 1:
1134 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1135 | ((data->fan_div[1] << 4) & 0x70);
1136 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1137 break;
1138 case 2:
1139 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1140 | (data->fan_div[2] & 0x7);
1141 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1142 break;
1143 case 3:
1144 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1145 | ((data->fan_div[3] << 4) & 0x70);
1146 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1147 break;
1148 }
1149}
1150
1151static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1152{
1153 if (data->kind == nct6775)
1154 nct6775_write_fan_div(data, nr);
1155}
1156
1157static void nct6775_update_fan_div(struct nct6775_data *data)
1158{
1159 u8 i;
1160
1161 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1162 data->fan_div[0] = i & 0x7;
1163 data->fan_div[1] = (i & 0x70) >> 4;
1164 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1165 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001166 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001167 data->fan_div[3] = (i & 0x70) >> 4;
1168}
1169
1170static void nct6775_update_fan_div_common(struct nct6775_data *data)
1171{
1172 if (data->kind == nct6775)
1173 nct6775_update_fan_div(data);
1174}
1175
1176static void nct6775_init_fan_div(struct nct6775_data *data)
1177{
1178 int i;
1179
1180 nct6775_update_fan_div_common(data);
1181 /*
1182 * For all fans, start with highest divider value if the divider
1183 * register is not initialized. This ensures that we get a
1184 * reading from the fan count register, even if it is not optimal.
1185 * We'll compute a better divider later on.
1186 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001187 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001188 if (!(data->has_fan & (1 << i)))
1189 continue;
1190 if (data->fan_div[i] == 0) {
1191 data->fan_div[i] = 7;
1192 nct6775_write_fan_div_common(data, i);
1193 }
1194 }
1195}
1196
1197static void nct6775_init_fan_common(struct device *dev,
1198 struct nct6775_data *data)
1199{
1200 int i;
1201 u8 reg;
1202
1203 if (data->has_fan_div)
1204 nct6775_init_fan_div(data);
1205
1206 /*
1207 * If fan_min is not set (0), set it to 0xff to disable it. This
1208 * prevents the unnecessary warning when fanX_min is reported as 0.
1209 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001210 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001211 if (data->has_fan_min & (1 << i)) {
1212 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1213 if (!reg)
1214 nct6775_write_value(data, data->REG_FAN_MIN[i],
1215 data->has_fan_div ? 0xff
1216 : 0xff1f);
1217 }
1218 }
1219}
1220
1221static void nct6775_select_fan_div(struct device *dev,
1222 struct nct6775_data *data, int nr, u16 reg)
1223{
1224 u8 fan_div = data->fan_div[nr];
1225 u16 fan_min;
1226
1227 if (!data->has_fan_div)
1228 return;
1229
1230 /*
1231 * If we failed to measure the fan speed, or the reported value is not
1232 * in the optimal range, and the clock divider can be modified,
1233 * let's try that for next time.
1234 */
1235 if (reg == 0x00 && fan_div < 0x07)
1236 fan_div++;
1237 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1238 fan_div--;
1239
1240 if (fan_div != data->fan_div[nr]) {
1241 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1242 nr + 1, div_from_reg(data->fan_div[nr]),
1243 div_from_reg(fan_div));
1244
1245 /* Preserve min limit if possible */
1246 if (data->has_fan_min & (1 << nr)) {
1247 fan_min = data->fan_min[nr];
1248 if (fan_div > data->fan_div[nr]) {
1249 if (fan_min != 255 && fan_min > 1)
1250 fan_min >>= 1;
1251 } else {
1252 if (fan_min != 255) {
1253 fan_min <<= 1;
1254 if (fan_min > 254)
1255 fan_min = 254;
1256 }
1257 }
1258 if (fan_min != data->fan_min[nr]) {
1259 data->fan_min[nr] = fan_min;
1260 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1261 fan_min);
1262 }
1263 }
1264 data->fan_div[nr] = fan_div;
1265 nct6775_write_fan_div_common(data, nr);
1266 }
1267}
1268
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001269static void nct6775_update_pwm(struct device *dev)
1270{
1271 struct nct6775_data *data = dev_get_drvdata(dev);
1272 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001273 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001274 bool duty_is_dc;
1275
1276 for (i = 0; i < data->pwm_num; i++) {
1277 if (!(data->has_pwm & (1 << i)))
1278 continue;
1279
1280 duty_is_dc = data->REG_PWM_MODE[i] &&
1281 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1282 & data->PWM_MODE_MASK[i]);
1283 data->pwm_mode[i] = duty_is_dc;
1284
1285 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1286 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1287 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1288 data->pwm[j][i]
1289 = nct6775_read_value(data,
1290 data->REG_PWM[j][i]);
1291 }
1292 }
1293
1294 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1295 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001296
1297 if (!data->temp_tolerance[0][i] ||
1298 data->pwm_enable[i] != speed_cruise)
1299 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1300 if (!data->target_speed_tolerance[i] ||
1301 data->pwm_enable[i] == speed_cruise) {
1302 u8 t = fanmodecfg & 0x0f;
1303 if (data->REG_TOLERANCE_H) {
1304 t |= (nct6775_read_value(data,
1305 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1306 }
1307 data->target_speed_tolerance[i] = t;
1308 }
1309
1310 data->temp_tolerance[1][i] =
1311 nct6775_read_value(data,
1312 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1313
1314 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1315 data->pwm_temp_sel[i] = reg & 0x1f;
1316 /* If fan can stop, report floor as 0 */
1317 if (reg & 0x80)
1318 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001319
Guenter Roeckcc76dee2013-11-13 12:47:17 -08001320 if (!data->REG_WEIGHT_TEMP_SEL[i])
1321 continue;
1322
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001323 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1324 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1325 /* If weight is disabled, report weight source as 0 */
1326 if (j == 1 && !(reg & 0x80))
1327 data->pwm_weight_temp_sel[i] = 0;
1328
1329 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001330 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001331 data->weight_temp[j][i]
1332 = nct6775_read_value(data,
1333 data->REG_WEIGHT_TEMP[j][i]);
1334 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001335 }
1336}
1337
1338static void nct6775_update_pwm_limits(struct device *dev)
1339{
1340 struct nct6775_data *data = dev_get_drvdata(dev);
1341 int i, j;
1342 u8 reg;
1343 u16 reg_t;
1344
1345 for (i = 0; i < data->pwm_num; i++) {
1346 if (!(data->has_pwm & (1 << i)))
1347 continue;
1348
Guenter Roeckc409fd42013-04-09 05:04:00 -07001349 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001350 data->fan_time[j][i] =
1351 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1352 }
1353
1354 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1355 /* Update only in matching mode or if never updated */
1356 if (!data->target_temp[i] ||
1357 data->pwm_enable[i] == thermal_cruise)
1358 data->target_temp[i] = reg_t & data->target_temp_mask;
1359 if (!data->target_speed[i] ||
1360 data->pwm_enable[i] == speed_cruise) {
1361 if (data->REG_TOLERANCE_H) {
1362 reg_t |= (nct6775_read_value(data,
1363 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1364 }
1365 data->target_speed[i] = reg_t;
1366 }
1367
1368 for (j = 0; j < data->auto_pwm_num; j++) {
1369 data->auto_pwm[i][j] =
1370 nct6775_read_value(data,
1371 NCT6775_AUTO_PWM(data, i, j));
1372 data->auto_temp[i][j] =
1373 nct6775_read_value(data,
1374 NCT6775_AUTO_TEMP(data, i, j));
1375 }
1376
1377 /* critical auto_pwm temperature data */
1378 data->auto_temp[i][data->auto_pwm_num] =
1379 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1380
1381 switch (data->kind) {
1382 case nct6775:
1383 reg = nct6775_read_value(data,
1384 NCT6775_REG_CRITICAL_ENAB[i]);
1385 data->auto_pwm[i][data->auto_pwm_num] =
1386 (reg & 0x02) ? 0xff : 0x00;
1387 break;
1388 case nct6776:
1389 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1390 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001391 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001392 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001393 case nct6791:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001394 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001395 data->REG_CRITICAL_PWM_ENABLE[i]);
1396 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1397 reg = nct6775_read_value(data,
1398 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001399 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001400 reg = 0xff;
1401 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001402 break;
1403 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001404 }
1405}
1406
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001407static struct nct6775_data *nct6775_update_device(struct device *dev)
1408{
1409 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001410 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001411
1412 mutex_lock(&data->update_lock);
1413
Guenter Roeck6445e662013-04-21 09:13:28 -07001414 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001415 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001416 /* Fan clock dividers */
1417 nct6775_update_fan_div_common(data);
1418
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001419 /* Measured voltages and limits */
1420 for (i = 0; i < data->in_num; i++) {
1421 if (!(data->have_in & (1 << i)))
1422 continue;
1423
1424 data->in[i][0] = nct6775_read_value(data,
1425 data->REG_VIN[i]);
1426 data->in[i][1] = nct6775_read_value(data,
1427 data->REG_IN_MINMAX[0][i]);
1428 data->in[i][2] = nct6775_read_value(data,
1429 data->REG_IN_MINMAX[1][i]);
1430 }
1431
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001432 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001433 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001434 u16 reg;
1435
1436 if (!(data->has_fan & (1 << i)))
1437 continue;
1438
1439 reg = nct6775_read_value(data, data->REG_FAN[i]);
1440 data->rpm[i] = data->fan_from_reg(reg,
1441 data->fan_div[i]);
1442
1443 if (data->has_fan_min & (1 << i))
1444 data->fan_min[i] = nct6775_read_value(data,
1445 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001446 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001447 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1448 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001449
1450 nct6775_select_fan_div(dev, data, i, reg);
1451 }
1452
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001453 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001454 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001455
Guenter Roeckaa136e52012-12-04 03:26:05 -08001456 /* Measured temperatures and limits */
1457 for (i = 0; i < NUM_TEMP; i++) {
1458 if (!(data->have_temp & (1 << i)))
1459 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001460 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001461 if (data->reg_temp[j][i])
1462 data->temp[j][i]
1463 = nct6775_read_temp(data,
1464 data->reg_temp[j][i]);
1465 }
Guenter Roeck45a5b3a2013-09-11 10:35:47 -07001466 if (i >= NUM_TEMP_FIXED ||
1467 !(data->have_temp_fixed & (1 << i)))
Guenter Roeckaa136e52012-12-04 03:26:05 -08001468 continue;
1469 data->temp_offset[i]
1470 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1471 }
1472
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001473 data->alarms = 0;
1474 for (i = 0; i < NUM_REG_ALARM; i++) {
1475 u8 alarm;
1476 if (!data->REG_ALARM[i])
1477 continue;
1478 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1479 data->alarms |= ((u64)alarm) << (i << 3);
1480 }
1481
Guenter Roeck30846992013-06-24 22:21:59 -07001482 data->beeps = 0;
1483 for (i = 0; i < NUM_REG_BEEP; i++) {
1484 u8 beep;
1485 if (!data->REG_BEEP[i])
1486 continue;
1487 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1488 data->beeps |= ((u64)beep) << (i << 3);
1489 }
1490
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001491 data->last_updated = jiffies;
1492 data->valid = true;
1493 }
1494
1495 mutex_unlock(&data->update_lock);
1496 return data;
1497}
1498
1499/*
1500 * Sysfs callback functions
1501 */
1502static ssize_t
1503show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1504{
1505 struct nct6775_data *data = nct6775_update_device(dev);
1506 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1507 int nr = sattr->nr;
1508 int index = sattr->index;
1509 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1510}
1511
1512static ssize_t
1513store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1514 size_t count)
1515{
1516 struct nct6775_data *data = dev_get_drvdata(dev);
1517 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1518 int nr = sattr->nr;
1519 int index = sattr->index;
1520 unsigned long val;
1521 int err = kstrtoul(buf, 10, &val);
1522 if (err < 0)
1523 return err;
1524 mutex_lock(&data->update_lock);
1525 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001526 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001527 data->in[nr][index]);
1528 mutex_unlock(&data->update_lock);
1529 return count;
1530}
1531
1532static ssize_t
1533show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1534{
1535 struct nct6775_data *data = nct6775_update_device(dev);
1536 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1537 int nr = data->ALARM_BITS[sattr->index];
1538 return sprintf(buf, "%u\n",
1539 (unsigned int)((data->alarms >> nr) & 0x01));
1540}
1541
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001542static int find_temp_source(struct nct6775_data *data, int index, int count)
1543{
1544 int source = data->temp_src[index];
1545 int nr;
1546
1547 for (nr = 0; nr < count; nr++) {
1548 int src;
1549
1550 src = nct6775_read_value(data,
1551 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1552 if (src == source)
1553 return nr;
1554 }
Guenter Roecke8ab5082013-09-11 10:32:18 -07001555 return -ENODEV;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001556}
1557
1558static ssize_t
1559show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1560{
1561 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1562 struct nct6775_data *data = nct6775_update_device(dev);
1563 unsigned int alarm = 0;
1564 int nr;
1565
1566 /*
1567 * For temperatures, there is no fixed mapping from registers to alarm
1568 * bits. Alarm bits are determined by the temperature source mapping.
1569 */
1570 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1571 if (nr >= 0) {
1572 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1573 alarm = (data->alarms >> bit) & 0x01;
1574 }
1575 return sprintf(buf, "%u\n", alarm);
1576}
1577
Guenter Roeck30846992013-06-24 22:21:59 -07001578static ssize_t
1579show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1580{
1581 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1582 struct nct6775_data *data = nct6775_update_device(dev);
1583 int nr = data->BEEP_BITS[sattr->index];
1584
1585 return sprintf(buf, "%u\n",
1586 (unsigned int)((data->beeps >> nr) & 0x01));
1587}
1588
1589static ssize_t
1590store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1591 size_t count)
1592{
1593 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1594 struct nct6775_data *data = dev_get_drvdata(dev);
1595 int nr = data->BEEP_BITS[sattr->index];
1596 int regindex = nr >> 3;
1597 unsigned long val;
1598
1599 int err = kstrtoul(buf, 10, &val);
1600 if (err < 0)
1601 return err;
1602 if (val > 1)
1603 return -EINVAL;
1604
1605 mutex_lock(&data->update_lock);
1606 if (val)
1607 data->beeps |= (1ULL << nr);
1608 else
1609 data->beeps &= ~(1ULL << nr);
1610 nct6775_write_value(data, data->REG_BEEP[regindex],
1611 (data->beeps >> (regindex << 3)) & 0xff);
1612 mutex_unlock(&data->update_lock);
1613 return count;
1614}
1615
1616static ssize_t
1617show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1618{
1619 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1620 struct nct6775_data *data = nct6775_update_device(dev);
1621 unsigned int beep = 0;
1622 int nr;
1623
1624 /*
1625 * For temperatures, there is no fixed mapping from registers to beep
1626 * enable bits. Beep enable bits are determined by the temperature
1627 * source mapping.
1628 */
1629 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1630 if (nr >= 0) {
1631 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1632 beep = (data->beeps >> bit) & 0x01;
1633 }
1634 return sprintf(buf, "%u\n", beep);
1635}
1636
1637static ssize_t
1638store_temp_beep(struct device *dev, struct device_attribute *attr,
1639 const char *buf, size_t count)
1640{
1641 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1642 struct nct6775_data *data = dev_get_drvdata(dev);
1643 int nr, bit, regindex;
1644 unsigned long val;
1645
1646 int err = kstrtoul(buf, 10, &val);
1647 if (err < 0)
1648 return err;
1649 if (val > 1)
1650 return -EINVAL;
1651
1652 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1653 if (nr < 0)
Guenter Roecke8ab5082013-09-11 10:32:18 -07001654 return nr;
Guenter Roeck30846992013-06-24 22:21:59 -07001655
1656 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1657 regindex = bit >> 3;
1658
1659 mutex_lock(&data->update_lock);
1660 if (val)
1661 data->beeps |= (1ULL << bit);
1662 else
1663 data->beeps &= ~(1ULL << bit);
1664 nct6775_write_value(data, data->REG_BEEP[regindex],
1665 (data->beeps >> (regindex << 3)) & 0xff);
1666 mutex_unlock(&data->update_lock);
1667
1668 return count;
1669}
1670
Guenter Roeckf73cf632013-03-18 09:22:50 -07001671static umode_t nct6775_in_is_visible(struct kobject *kobj,
1672 struct attribute *attr, int index)
1673{
1674 struct device *dev = container_of(kobj, struct device, kobj);
1675 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001676 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001677
Guenter Roeckf73cf632013-03-18 09:22:50 -07001678 if (!(data->have_in & (1 << in)))
1679 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001680
Guenter Roeckf73cf632013-03-18 09:22:50 -07001681 return attr->mode;
1682}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001683
Guenter Roeckf73cf632013-03-18 09:22:50 -07001684SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1685SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001686SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1687 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001688SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1689 store_in_reg, 0, 1);
1690SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1691 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001692
Guenter Roeckf73cf632013-03-18 09:22:50 -07001693/*
1694 * nct6775_in_is_visible uses the index into the following array
1695 * to determine if attributes should be created or not.
1696 * Any change in order or content must be matched.
1697 */
1698static struct sensor_device_template *nct6775_attributes_in_template[] = {
1699 &sensor_dev_template_in_input,
1700 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001701 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001702 &sensor_dev_template_in_min,
1703 &sensor_dev_template_in_max,
1704 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001705};
1706
Guenter Roeckf73cf632013-03-18 09:22:50 -07001707static struct sensor_template_group nct6775_in_template_group = {
1708 .templates = nct6775_attributes_in_template,
1709 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001710};
1711
1712static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001713show_fan(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", data->rpm[nr]);
1719}
1720
1721static ssize_t
1722show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1723{
1724 struct nct6775_data *data = nct6775_update_device(dev);
1725 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1726 int nr = sattr->index;
1727 return sprintf(buf, "%d\n",
1728 data->fan_from_reg_min(data->fan_min[nr],
1729 data->fan_div[nr]));
1730}
1731
1732static ssize_t
1733show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1734{
1735 struct nct6775_data *data = nct6775_update_device(dev);
1736 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1737 int nr = sattr->index;
1738 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1739}
1740
1741static ssize_t
1742store_fan_min(struct device *dev, struct device_attribute *attr,
1743 const char *buf, size_t count)
1744{
1745 struct nct6775_data *data = dev_get_drvdata(dev);
1746 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1747 int nr = sattr->index;
1748 unsigned long val;
1749 int err;
1750 unsigned int reg;
1751 u8 new_div;
1752
1753 err = kstrtoul(buf, 10, &val);
1754 if (err < 0)
1755 return err;
1756
1757 mutex_lock(&data->update_lock);
1758 if (!data->has_fan_div) {
1759 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1760 if (!val) {
1761 val = 0xff1f;
1762 } else {
1763 if (val > 1350000U)
1764 val = 135000U;
1765 val = 1350000U / val;
1766 val = (val & 0x1f) | ((val << 3) & 0xff00);
1767 }
1768 data->fan_min[nr] = val;
1769 goto write_min; /* Leave fan divider alone */
1770 }
1771 if (!val) {
1772 /* No min limit, alarm disabled */
1773 data->fan_min[nr] = 255;
1774 new_div = data->fan_div[nr]; /* No change */
1775 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1776 goto write_div;
1777 }
1778 reg = 1350000U / val;
1779 if (reg >= 128 * 255) {
1780 /*
1781 * Speed below this value cannot possibly be represented,
1782 * even with the highest divider (128)
1783 */
1784 data->fan_min[nr] = 254;
1785 new_div = 7; /* 128 == (1 << 7) */
1786 dev_warn(dev,
1787 "fan%u low limit %lu below minimum %u, set to minimum\n",
1788 nr + 1, val, data->fan_from_reg_min(254, 7));
1789 } else if (!reg) {
1790 /*
1791 * Speed above this value cannot possibly be represented,
1792 * even with the lowest divider (1)
1793 */
1794 data->fan_min[nr] = 1;
1795 new_div = 0; /* 1 == (1 << 0) */
1796 dev_warn(dev,
1797 "fan%u low limit %lu above maximum %u, set to maximum\n",
1798 nr + 1, val, data->fan_from_reg_min(1, 0));
1799 } else {
1800 /*
1801 * Automatically pick the best divider, i.e. the one such
1802 * that the min limit will correspond to a register value
1803 * in the 96..192 range
1804 */
1805 new_div = 0;
1806 while (reg > 192 && new_div < 7) {
1807 reg >>= 1;
1808 new_div++;
1809 }
1810 data->fan_min[nr] = reg;
1811 }
1812
1813write_div:
1814 /*
1815 * Write both the fan clock divider (if it changed) and the new
1816 * fan min (unconditionally)
1817 */
1818 if (new_div != data->fan_div[nr]) {
1819 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1820 nr + 1, div_from_reg(data->fan_div[nr]),
1821 div_from_reg(new_div));
1822 data->fan_div[nr] = new_div;
1823 nct6775_write_fan_div_common(data, nr);
1824 /* Give the chip time to sample a new speed value */
1825 data->last_updated = jiffies;
1826 }
1827
1828write_min:
1829 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1830 mutex_unlock(&data->update_lock);
1831
1832 return count;
1833}
1834
Guenter Roeck5c25d952012-12-11 07:29:06 -08001835static ssize_t
1836show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1837{
1838 struct nct6775_data *data = nct6775_update_device(dev);
1839 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1840 int p = data->fan_pulses[sattr->index];
1841
1842 return sprintf(buf, "%d\n", p ? : 4);
1843}
1844
1845static ssize_t
1846store_fan_pulses(struct device *dev, struct device_attribute *attr,
1847 const char *buf, size_t count)
1848{
1849 struct nct6775_data *data = dev_get_drvdata(dev);
1850 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1851 int nr = sattr->index;
1852 unsigned long val;
1853 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001854 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001855
1856 err = kstrtoul(buf, 10, &val);
1857 if (err < 0)
1858 return err;
1859
1860 if (val > 4)
1861 return -EINVAL;
1862
1863 mutex_lock(&data->update_lock);
1864 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001865 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1866 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1867 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1868 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001869 mutex_unlock(&data->update_lock);
1870
1871 return count;
1872}
1873
Guenter Roeckf73cf632013-03-18 09:22:50 -07001874static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1875 struct attribute *attr, int index)
1876{
1877 struct device *dev = container_of(kobj, struct device, kobj);
1878 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001879 int fan = index / 6; /* fan index */
1880 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001881
1882 if (!(data->has_fan & (1 << fan)))
1883 return 0;
1884
1885 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1886 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001887 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001888 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001889 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1890 return 0;
1891 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001892 return 0;
1893
1894 return attr->mode;
1895}
1896
1897SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1898SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1899 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001900SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1901 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001902SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1903 store_fan_pulses, 0);
1904SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1905 store_fan_min, 0);
1906SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1907
1908/*
1909 * nct6775_fan_is_visible uses the index into the following array
1910 * to determine if attributes should be created or not.
1911 * Any change in order or content must be matched.
1912 */
1913static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1914 &sensor_dev_template_fan_input,
1915 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001916 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001917 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001918 &sensor_dev_template_fan_min, /* 4 */
1919 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001920 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001921};
1922
Guenter Roeckf73cf632013-03-18 09:22:50 -07001923static struct sensor_template_group nct6775_fan_template_group = {
1924 .templates = nct6775_attributes_fan_template,
1925 .is_visible = nct6775_fan_is_visible,
1926 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001927};
1928
1929static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001930show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1931{
1932 struct nct6775_data *data = nct6775_update_device(dev);
1933 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1934 int nr = sattr->index;
1935 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1936}
1937
1938static ssize_t
1939show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1940{
1941 struct nct6775_data *data = nct6775_update_device(dev);
1942 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1943 int nr = sattr->nr;
1944 int index = sattr->index;
1945
1946 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1947}
1948
1949static ssize_t
1950store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1951 size_t count)
1952{
1953 struct nct6775_data *data = dev_get_drvdata(dev);
1954 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1955 int nr = sattr->nr;
1956 int index = sattr->index;
1957 int err;
1958 long val;
1959
1960 err = kstrtol(buf, 10, &val);
1961 if (err < 0)
1962 return err;
1963
1964 mutex_lock(&data->update_lock);
1965 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1966 nct6775_write_temp(data, data->reg_temp[index][nr],
1967 data->temp[index][nr]);
1968 mutex_unlock(&data->update_lock);
1969 return count;
1970}
1971
1972static ssize_t
1973show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1974{
1975 struct nct6775_data *data = nct6775_update_device(dev);
1976 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1977
1978 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1979}
1980
1981static ssize_t
1982store_temp_offset(struct device *dev, struct device_attribute *attr,
1983 const char *buf, size_t count)
1984{
1985 struct nct6775_data *data = dev_get_drvdata(dev);
1986 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1987 int nr = sattr->index;
1988 long val;
1989 int err;
1990
1991 err = kstrtol(buf, 10, &val);
1992 if (err < 0)
1993 return err;
1994
1995 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1996
1997 mutex_lock(&data->update_lock);
1998 data->temp_offset[nr] = val;
1999 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
2000 mutex_unlock(&data->update_lock);
2001
2002 return count;
2003}
2004
2005static ssize_t
2006show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
2007{
2008 struct nct6775_data *data = nct6775_update_device(dev);
2009 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2010 int nr = sattr->index;
2011 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2012}
2013
2014static ssize_t
2015store_temp_type(struct device *dev, struct device_attribute *attr,
2016 const char *buf, size_t count)
2017{
2018 struct nct6775_data *data = nct6775_update_device(dev);
2019 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2020 int nr = sattr->index;
2021 unsigned long val;
2022 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002023 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002024
2025 err = kstrtoul(buf, 10, &val);
2026 if (err < 0)
2027 return err;
2028
2029 if (val != 1 && val != 3 && val != 4)
2030 return -EINVAL;
2031
2032 mutex_lock(&data->update_lock);
2033
2034 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002035 vbit = 0x02 << nr;
2036 dbit = data->DIODE_MASK << nr;
2037 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2038 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002039 switch (val) {
2040 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002041 vbat |= vbit;
2042 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002043 break;
2044 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002045 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002046 break;
2047 case 4: /* thermistor */
2048 break;
2049 }
2050 nct6775_write_value(data, data->REG_VBAT, vbat);
2051 nct6775_write_value(data, data->REG_DIODE, diode);
2052
2053 mutex_unlock(&data->update_lock);
2054 return count;
2055}
2056
Guenter Roeckf73cf632013-03-18 09:22:50 -07002057static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2058 struct attribute *attr, int index)
2059{
2060 struct device *dev = container_of(kobj, struct device, kobj);
2061 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002062 int temp = index / 10; /* temp index */
2063 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002064
2065 if (!(data->have_temp & (1 << temp)))
2066 return 0;
2067
2068 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2069 return 0; /* alarm */
2070
Guenter Roeck30846992013-06-24 22:21:59 -07002071 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2072 return 0; /* beep */
2073
2074 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002075 return 0;
2076
Guenter Roeck30846992013-06-24 22:21:59 -07002077 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002078 return 0;
2079
Guenter Roeck30846992013-06-24 22:21:59 -07002080 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002081 return 0;
2082
Guenter Roeck30846992013-06-24 22:21:59 -07002083 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002084 return 0;
2085
2086 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002087 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002088 return 0;
2089
2090 return attr->mode;
2091}
2092
2093SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2094SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2095SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2096 store_temp, 0, 1);
2097SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2098 show_temp, store_temp, 0, 2);
2099SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2100 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002101SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2102 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002103SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2104 show_temp_offset, store_temp_offset, 0);
2105SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2106 store_temp_type, 0);
2107SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002108SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2109 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002110
2111/*
2112 * nct6775_temp_is_visible uses the index into the following array
2113 * to determine if attributes should be created or not.
2114 * Any change in order or content must be matched.
2115 */
2116static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2117 &sensor_dev_template_temp_input,
2118 &sensor_dev_template_temp_label,
2119 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002120 &sensor_dev_template_temp_beep, /* 3 */
2121 &sensor_dev_template_temp_max, /* 4 */
2122 &sensor_dev_template_temp_max_hyst, /* 5 */
2123 &sensor_dev_template_temp_crit, /* 6 */
2124 &sensor_dev_template_temp_lcrit, /* 7 */
2125 &sensor_dev_template_temp_offset, /* 8 */
2126 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002127 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002128};
2129
Guenter Roeckf73cf632013-03-18 09:22:50 -07002130static struct sensor_template_group nct6775_temp_template_group = {
2131 .templates = nct6775_attributes_temp_template,
2132 .is_visible = nct6775_temp_is_visible,
2133 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002134};
2135
Guenter Roeckaa136e52012-12-04 03:26:05 -08002136static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002137show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2138{
2139 struct nct6775_data *data = nct6775_update_device(dev);
2140 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2141
2142 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2143}
2144
2145static ssize_t
2146store_pwm_mode(struct device *dev, struct device_attribute *attr,
2147 const char *buf, size_t count)
2148{
2149 struct nct6775_data *data = dev_get_drvdata(dev);
2150 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2151 int nr = sattr->index;
2152 unsigned long val;
2153 int err;
2154 u8 reg;
2155
2156 err = kstrtoul(buf, 10, &val);
2157 if (err < 0)
2158 return err;
2159
2160 if (val > 1)
2161 return -EINVAL;
2162
2163 /* Setting DC mode is not supported for all chips/channels */
2164 if (data->REG_PWM_MODE[nr] == 0) {
2165 if (val)
2166 return -EINVAL;
2167 return count;
2168 }
2169
2170 mutex_lock(&data->update_lock);
2171 data->pwm_mode[nr] = val;
2172 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2173 reg &= ~data->PWM_MODE_MASK[nr];
2174 if (val)
2175 reg |= data->PWM_MODE_MASK[nr];
2176 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2177 mutex_unlock(&data->update_lock);
2178 return count;
2179}
2180
2181static ssize_t
2182show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2183{
2184 struct nct6775_data *data = nct6775_update_device(dev);
2185 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2186 int nr = sattr->nr;
2187 int index = sattr->index;
2188 int pwm;
2189
2190 /*
2191 * For automatic fan control modes, show current pwm readings.
2192 * Otherwise, show the configured value.
2193 */
2194 if (index == 0 && data->pwm_enable[nr] > manual)
2195 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2196 else
2197 pwm = data->pwm[index][nr];
2198
2199 return sprintf(buf, "%d\n", pwm);
2200}
2201
2202static ssize_t
2203store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2204 size_t count)
2205{
2206 struct nct6775_data *data = dev_get_drvdata(dev);
2207 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2208 int nr = sattr->nr;
2209 int index = sattr->index;
2210 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002211 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2212 int maxval[7]
2213 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002214 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002215 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002216
2217 err = kstrtoul(buf, 10, &val);
2218 if (err < 0)
2219 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002220 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002221
2222 mutex_lock(&data->update_lock);
2223 data->pwm[index][nr] = val;
2224 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002225 if (index == 2) { /* floor: disable if val == 0 */
2226 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2227 reg &= 0x7f;
2228 if (val)
2229 reg |= 0x80;
2230 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2231 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002232 mutex_unlock(&data->update_lock);
2233 return count;
2234}
2235
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002236/* Returns 0 if OK, -EINVAL otherwise */
2237static int check_trip_points(struct nct6775_data *data, int nr)
2238{
2239 int i;
2240
2241 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2242 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2243 return -EINVAL;
2244 }
2245 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2246 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2247 return -EINVAL;
2248 }
2249 /* validate critical temperature and pwm if enabled (pwm > 0) */
2250 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2251 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2252 data->auto_temp[nr][data->auto_pwm_num] ||
2253 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2254 data->auto_pwm[nr][data->auto_pwm_num])
2255 return -EINVAL;
2256 }
2257 return 0;
2258}
2259
2260static void pwm_update_registers(struct nct6775_data *data, int nr)
2261{
2262 u8 reg;
2263
2264 switch (data->pwm_enable[nr]) {
2265 case off:
2266 case manual:
2267 break;
2268 case speed_cruise:
2269 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2270 reg = (reg & ~data->tolerance_mask) |
2271 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2272 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2273 nct6775_write_value(data, data->REG_TARGET[nr],
2274 data->target_speed[nr] & 0xff);
2275 if (data->REG_TOLERANCE_H) {
2276 reg = (data->target_speed[nr] >> 8) & 0x0f;
2277 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2278 nct6775_write_value(data,
2279 data->REG_TOLERANCE_H[nr],
2280 reg);
2281 }
2282 break;
2283 case thermal_cruise:
2284 nct6775_write_value(data, data->REG_TARGET[nr],
2285 data->target_temp[nr]);
2286 /* intentional */
2287 default:
2288 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2289 reg = (reg & ~data->tolerance_mask) |
2290 data->temp_tolerance[0][nr];
2291 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2292 break;
2293 }
2294}
2295
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002296static ssize_t
2297show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2298{
2299 struct nct6775_data *data = nct6775_update_device(dev);
2300 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2301
2302 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2303}
2304
2305static ssize_t
2306store_pwm_enable(struct device *dev, struct device_attribute *attr,
2307 const char *buf, size_t count)
2308{
2309 struct nct6775_data *data = dev_get_drvdata(dev);
2310 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2311 int nr = sattr->index;
2312 unsigned long val;
2313 int err;
2314 u16 reg;
2315
2316 err = kstrtoul(buf, 10, &val);
2317 if (err < 0)
2318 return err;
2319
2320 if (val > sf4)
2321 return -EINVAL;
2322
2323 if (val == sf3 && data->kind != nct6775)
2324 return -EINVAL;
2325
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002326 if (val == sf4 && check_trip_points(data, nr)) {
2327 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2328 dev_err(dev, "Adjust trip points and try again\n");
2329 return -EINVAL;
2330 }
2331
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002332 mutex_lock(&data->update_lock);
2333 data->pwm_enable[nr] = val;
2334 if (val == off) {
2335 /*
2336 * turn off pwm control: select manual mode, set pwm to maximum
2337 */
2338 data->pwm[0][nr] = 255;
2339 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2340 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002341 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002342 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2343 reg &= 0x0f;
2344 reg |= pwm_enable_to_reg(val) << 4;
2345 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2346 mutex_unlock(&data->update_lock);
2347 return count;
2348}
2349
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002350static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002351show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002352{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002353 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002354
2355 for (i = 0; i < NUM_TEMP; i++) {
2356 if (!(data->have_temp & (1 << i)))
2357 continue;
2358 if (src == data->temp_src[i]) {
2359 sel = i + 1;
2360 break;
2361 }
2362 }
2363
2364 return sprintf(buf, "%d\n", sel);
2365}
2366
2367static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002368show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2369{
2370 struct nct6775_data *data = nct6775_update_device(dev);
2371 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2372 int index = sattr->index;
2373
2374 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2375}
2376
2377static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002378store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2379 const char *buf, size_t count)
2380{
2381 struct nct6775_data *data = nct6775_update_device(dev);
2382 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2383 int nr = sattr->index;
2384 unsigned long val;
2385 int err, reg, src;
2386
2387 err = kstrtoul(buf, 10, &val);
2388 if (err < 0)
2389 return err;
2390 if (val == 0 || val > NUM_TEMP)
2391 return -EINVAL;
2392 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2393 return -EINVAL;
2394
2395 mutex_lock(&data->update_lock);
2396 src = data->temp_src[val - 1];
2397 data->pwm_temp_sel[nr] = src;
2398 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2399 reg &= 0xe0;
2400 reg |= src;
2401 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2402 mutex_unlock(&data->update_lock);
2403
2404 return count;
2405}
2406
2407static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002408show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2409 char *buf)
2410{
2411 struct nct6775_data *data = nct6775_update_device(dev);
2412 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2413 int index = sattr->index;
2414
2415 return show_pwm_temp_sel_common(data, buf,
2416 data->pwm_weight_temp_sel[index]);
2417}
2418
2419static ssize_t
2420store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2421 const char *buf, size_t count)
2422{
2423 struct nct6775_data *data = nct6775_update_device(dev);
2424 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2425 int nr = sattr->index;
2426 unsigned long val;
2427 int err, reg, src;
2428
2429 err = kstrtoul(buf, 10, &val);
2430 if (err < 0)
2431 return err;
2432 if (val > NUM_TEMP)
2433 return -EINVAL;
2434 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2435 !data->temp_src[val - 1]))
2436 return -EINVAL;
2437
2438 mutex_lock(&data->update_lock);
2439 if (val) {
2440 src = data->temp_src[val - 1];
2441 data->pwm_weight_temp_sel[nr] = src;
2442 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2443 reg &= 0xe0;
2444 reg |= (src | 0x80);
2445 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2446 } else {
2447 data->pwm_weight_temp_sel[nr] = 0;
2448 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2449 reg &= 0x7f;
2450 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2451 }
2452 mutex_unlock(&data->update_lock);
2453
2454 return count;
2455}
2456
2457static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002458show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2459{
2460 struct nct6775_data *data = nct6775_update_device(dev);
2461 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2462
2463 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2464}
2465
2466static ssize_t
2467store_target_temp(struct device *dev, struct device_attribute *attr,
2468 const char *buf, size_t count)
2469{
2470 struct nct6775_data *data = dev_get_drvdata(dev);
2471 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2472 int nr = sattr->index;
2473 unsigned long val;
2474 int err;
2475
2476 err = kstrtoul(buf, 10, &val);
2477 if (err < 0)
2478 return err;
2479
2480 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2481 data->target_temp_mask);
2482
2483 mutex_lock(&data->update_lock);
2484 data->target_temp[nr] = val;
2485 pwm_update_registers(data, nr);
2486 mutex_unlock(&data->update_lock);
2487 return count;
2488}
2489
2490static ssize_t
2491show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2492{
2493 struct nct6775_data *data = nct6775_update_device(dev);
2494 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2495 int nr = sattr->index;
2496
2497 return sprintf(buf, "%d\n",
2498 fan_from_reg16(data->target_speed[nr],
2499 data->fan_div[nr]));
2500}
2501
2502static ssize_t
2503store_target_speed(struct device *dev, struct device_attribute *attr,
2504 const char *buf, size_t count)
2505{
2506 struct nct6775_data *data = dev_get_drvdata(dev);
2507 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2508 int nr = sattr->index;
2509 unsigned long val;
2510 int err;
2511 u16 speed;
2512
2513 err = kstrtoul(buf, 10, &val);
2514 if (err < 0)
2515 return err;
2516
2517 val = clamp_val(val, 0, 1350000U);
2518 speed = fan_to_reg(val, data->fan_div[nr]);
2519
2520 mutex_lock(&data->update_lock);
2521 data->target_speed[nr] = speed;
2522 pwm_update_registers(data, nr);
2523 mutex_unlock(&data->update_lock);
2524 return count;
2525}
2526
2527static ssize_t
2528show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2529 char *buf)
2530{
2531 struct nct6775_data *data = nct6775_update_device(dev);
2532 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2533 int nr = sattr->nr;
2534 int index = sattr->index;
2535
2536 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2537}
2538
2539static ssize_t
2540store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2541 const char *buf, size_t count)
2542{
2543 struct nct6775_data *data = dev_get_drvdata(dev);
2544 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2545 int nr = sattr->nr;
2546 int index = sattr->index;
2547 unsigned long val;
2548 int err;
2549
2550 err = kstrtoul(buf, 10, &val);
2551 if (err < 0)
2552 return err;
2553
2554 /* Limit tolerance as needed */
2555 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2556
2557 mutex_lock(&data->update_lock);
2558 data->temp_tolerance[index][nr] = val;
2559 if (index)
2560 pwm_update_registers(data, nr);
2561 else
2562 nct6775_write_value(data,
2563 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2564 val);
2565 mutex_unlock(&data->update_lock);
2566 return count;
2567}
2568
2569/*
2570 * Fan speed tolerance is a tricky beast, since the associated register is
2571 * a tick counter, but the value is reported and configured as rpm.
2572 * Compute resulting low and high rpm values and report the difference.
2573 */
2574static ssize_t
2575show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2576 char *buf)
2577{
2578 struct nct6775_data *data = nct6775_update_device(dev);
2579 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2580 int nr = sattr->index;
2581 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2582 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2583 int tolerance;
2584
2585 if (low <= 0)
2586 low = 1;
2587 if (high > 0xffff)
2588 high = 0xffff;
2589 if (high < low)
2590 high = low;
2591
2592 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2593 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2594
2595 return sprintf(buf, "%d\n", tolerance);
2596}
2597
2598static ssize_t
2599store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2600 const char *buf, size_t count)
2601{
2602 struct nct6775_data *data = dev_get_drvdata(dev);
2603 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2604 int nr = sattr->index;
2605 unsigned long val;
2606 int err;
2607 int low, high;
2608
2609 err = kstrtoul(buf, 10, &val);
2610 if (err < 0)
2611 return err;
2612
2613 high = fan_from_reg16(data->target_speed[nr],
2614 data->fan_div[nr]) + val;
2615 low = fan_from_reg16(data->target_speed[nr],
2616 data->fan_div[nr]) - val;
2617 if (low <= 0)
2618 low = 1;
2619 if (high < low)
2620 high = low;
2621
2622 val = (fan_to_reg(low, data->fan_div[nr]) -
2623 fan_to_reg(high, data->fan_div[nr])) / 2;
2624
2625 /* Limit tolerance as needed */
2626 val = clamp_val(val, 0, data->speed_tolerance_limit);
2627
2628 mutex_lock(&data->update_lock);
2629 data->target_speed_tolerance[nr] = val;
2630 pwm_update_registers(data, nr);
2631 mutex_unlock(&data->update_lock);
2632 return count;
2633}
2634
Guenter Roeckf73cf632013-03-18 09:22:50 -07002635SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2636SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2637 store_pwm_mode, 0);
2638SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2639 store_pwm_enable, 0);
2640SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2641 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2642SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2643 show_target_temp, store_target_temp, 0);
2644SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2645 show_target_speed, store_target_speed, 0);
2646SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2647 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002648
2649/* Smart Fan registers */
2650
2651static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002652show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2653{
2654 struct nct6775_data *data = nct6775_update_device(dev);
2655 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2656 int nr = sattr->nr;
2657 int index = sattr->index;
2658
2659 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2660}
2661
2662static ssize_t
2663store_weight_temp(struct device *dev, struct device_attribute *attr,
2664 const char *buf, size_t count)
2665{
2666 struct nct6775_data *data = dev_get_drvdata(dev);
2667 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2668 int nr = sattr->nr;
2669 int index = sattr->index;
2670 unsigned long val;
2671 int err;
2672
2673 err = kstrtoul(buf, 10, &val);
2674 if (err < 0)
2675 return err;
2676
2677 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2678
2679 mutex_lock(&data->update_lock);
2680 data->weight_temp[index][nr] = val;
2681 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2682 mutex_unlock(&data->update_lock);
2683 return count;
2684}
2685
Guenter Roeckf73cf632013-03-18 09:22:50 -07002686SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2687 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2688SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2689 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2690SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2691 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2692SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2693 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2694SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2695 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2696SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2697 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002698
2699static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002700show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2701{
2702 struct nct6775_data *data = nct6775_update_device(dev);
2703 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2704 int nr = sattr->nr;
2705 int index = sattr->index;
2706
2707 return sprintf(buf, "%d\n",
2708 step_time_from_reg(data->fan_time[index][nr],
2709 data->pwm_mode[nr]));
2710}
2711
2712static ssize_t
2713store_fan_time(struct device *dev, struct device_attribute *attr,
2714 const char *buf, size_t count)
2715{
2716 struct nct6775_data *data = dev_get_drvdata(dev);
2717 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2718 int nr = sattr->nr;
2719 int index = sattr->index;
2720 unsigned long val;
2721 int err;
2722
2723 err = kstrtoul(buf, 10, &val);
2724 if (err < 0)
2725 return err;
2726
2727 val = step_time_to_reg(val, data->pwm_mode[nr]);
2728 mutex_lock(&data->update_lock);
2729 data->fan_time[index][nr] = val;
2730 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2731 mutex_unlock(&data->update_lock);
2732 return count;
2733}
2734
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002735static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002736show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2737{
2738 struct nct6775_data *data = nct6775_update_device(dev);
2739 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2740
2741 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2742}
2743
2744static ssize_t
2745store_auto_pwm(struct device *dev, struct device_attribute *attr,
2746 const char *buf, size_t count)
2747{
2748 struct nct6775_data *data = dev_get_drvdata(dev);
2749 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2750 int nr = sattr->nr;
2751 int point = sattr->index;
2752 unsigned long val;
2753 int err;
2754 u8 reg;
2755
2756 err = kstrtoul(buf, 10, &val);
2757 if (err < 0)
2758 return err;
2759 if (val > 255)
2760 return -EINVAL;
2761
2762 if (point == data->auto_pwm_num) {
2763 if (data->kind != nct6775 && !val)
2764 return -EINVAL;
2765 if (data->kind != nct6779 && val)
2766 val = 0xff;
2767 }
2768
2769 mutex_lock(&data->update_lock);
2770 data->auto_pwm[nr][point] = val;
2771 if (point < data->auto_pwm_num) {
2772 nct6775_write_value(data,
2773 NCT6775_AUTO_PWM(data, nr, point),
2774 data->auto_pwm[nr][point]);
2775 } else {
2776 switch (data->kind) {
2777 case nct6775:
2778 /* disable if needed (pwm == 0) */
2779 reg = nct6775_read_value(data,
2780 NCT6775_REG_CRITICAL_ENAB[nr]);
2781 if (val)
2782 reg |= 0x02;
2783 else
2784 reg &= ~0x02;
2785 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2786 reg);
2787 break;
2788 case nct6776:
2789 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002790 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002791 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002792 case nct6791:
Guenter Roeck6c009502012-07-01 08:23:15 -07002793 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002794 val);
2795 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002796 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002797 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002798 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002799 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002800 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002801 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002802 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002803 reg);
2804 break;
2805 }
2806 }
2807 mutex_unlock(&data->update_lock);
2808 return count;
2809}
2810
2811static ssize_t
2812show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2813{
2814 struct nct6775_data *data = nct6775_update_device(dev);
2815 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2816 int nr = sattr->nr;
2817 int point = sattr->index;
2818
2819 /*
2820 * We don't know for sure if the temperature is signed or unsigned.
2821 * Assume it is unsigned.
2822 */
2823 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2824}
2825
2826static ssize_t
2827store_auto_temp(struct device *dev, struct device_attribute *attr,
2828 const char *buf, size_t count)
2829{
2830 struct nct6775_data *data = dev_get_drvdata(dev);
2831 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2832 int nr = sattr->nr;
2833 int point = sattr->index;
2834 unsigned long val;
2835 int err;
2836
2837 err = kstrtoul(buf, 10, &val);
2838 if (err)
2839 return err;
2840 if (val > 255000)
2841 return -EINVAL;
2842
2843 mutex_lock(&data->update_lock);
2844 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2845 if (point < data->auto_pwm_num) {
2846 nct6775_write_value(data,
2847 NCT6775_AUTO_TEMP(data, nr, point),
2848 data->auto_temp[nr][point]);
2849 } else {
2850 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2851 data->auto_temp[nr][point]);
2852 }
2853 mutex_unlock(&data->update_lock);
2854 return count;
2855}
2856
Guenter Roeckf73cf632013-03-18 09:22:50 -07002857static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2858 struct attribute *attr, int index)
2859{
2860 struct device *dev = container_of(kobj, struct device, kobj);
2861 struct nct6775_data *data = dev_get_drvdata(dev);
2862 int pwm = index / 36; /* pwm index */
2863 int nr = index % 36; /* attribute index */
2864
2865 if (!(data->has_pwm & (1 << pwm)))
2866 return 0;
2867
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002868 if ((nr >= 14 && nr <= 18) || nr == 21) /* weight */
2869 if (!data->REG_WEIGHT_TEMP_SEL[pwm])
2870 return 0;
Guenter Roeckf73cf632013-03-18 09:22:50 -07002871 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2872 return 0;
2873 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2874 return 0;
2875 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2876 return 0;
2877
2878 if (nr >= 22 && nr <= 35) { /* auto point */
2879 int api = (nr - 22) / 2; /* auto point index */
2880
2881 if (api > data->auto_pwm_num)
2882 return 0;
2883 }
2884 return attr->mode;
2885}
2886
2887SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2888 show_fan_time, store_fan_time, 0, 0);
2889SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2890 show_fan_time, store_fan_time, 0, 1);
2891SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2892 show_fan_time, store_fan_time, 0, 2);
2893SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2894 store_pwm, 0, 1);
2895SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2896 store_pwm, 0, 2);
2897SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2898 show_temp_tolerance, store_temp_tolerance, 0, 0);
2899SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2900 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2901 0, 1);
2902
2903SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2904 0, 3);
2905
2906SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2907 store_pwm, 0, 4);
2908
2909SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2910 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2911SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2912 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2913
2914SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2915 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2916SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2917 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2918
2919SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2920 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2921SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2922 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2923
2924SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2925 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2926SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2927 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2928
2929SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2930 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2931SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2932 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2933
2934SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2935 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2936SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2937 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2938
2939SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2940 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2941SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2942 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2943
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002944/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002945 * nct6775_pwm_is_visible uses the index into the following array
2946 * to determine if attributes should be created or not.
2947 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002948 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002949static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2950 &sensor_dev_template_pwm,
2951 &sensor_dev_template_pwm_mode,
2952 &sensor_dev_template_pwm_enable,
2953 &sensor_dev_template_pwm_temp_sel,
2954 &sensor_dev_template_pwm_temp_tolerance,
2955 &sensor_dev_template_pwm_crit_temp_tolerance,
2956 &sensor_dev_template_pwm_target_temp,
2957 &sensor_dev_template_fan_target,
2958 &sensor_dev_template_fan_tolerance,
2959 &sensor_dev_template_pwm_stop_time,
2960 &sensor_dev_template_pwm_step_up_time,
2961 &sensor_dev_template_pwm_step_down_time,
2962 &sensor_dev_template_pwm_start,
2963 &sensor_dev_template_pwm_floor,
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002964 &sensor_dev_template_pwm_weight_temp_sel, /* 14 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002965 &sensor_dev_template_pwm_weight_temp_step,
2966 &sensor_dev_template_pwm_weight_temp_step_tol,
2967 &sensor_dev_template_pwm_weight_temp_step_base,
Guenter Roeckcc76dee2013-11-13 12:47:17 -08002968 &sensor_dev_template_pwm_weight_duty_step, /* 18 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002969 &sensor_dev_template_pwm_max, /* 19 */
2970 &sensor_dev_template_pwm_step, /* 20 */
2971 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2972 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2973 &sensor_dev_template_pwm_auto_point1_temp,
2974 &sensor_dev_template_pwm_auto_point2_pwm,
2975 &sensor_dev_template_pwm_auto_point2_temp,
2976 &sensor_dev_template_pwm_auto_point3_pwm,
2977 &sensor_dev_template_pwm_auto_point3_temp,
2978 &sensor_dev_template_pwm_auto_point4_pwm,
2979 &sensor_dev_template_pwm_auto_point4_temp,
2980 &sensor_dev_template_pwm_auto_point5_pwm,
2981 &sensor_dev_template_pwm_auto_point5_temp,
2982 &sensor_dev_template_pwm_auto_point6_pwm,
2983 &sensor_dev_template_pwm_auto_point6_temp,
2984 &sensor_dev_template_pwm_auto_point7_pwm,
2985 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002986
Guenter Roeckf73cf632013-03-18 09:22:50 -07002987 NULL
2988};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002989
Guenter Roeckf73cf632013-03-18 09:22:50 -07002990static struct sensor_template_group nct6775_pwm_template_group = {
2991 .templates = nct6775_attributes_pwm_template,
2992 .is_visible = nct6775_pwm_is_visible,
2993 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002994};
2995
2996static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002997show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2998{
2999 struct nct6775_data *data = dev_get_drvdata(dev);
3000 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
3001}
3002
3003static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
3004
Guenter Roecka6bd5872012-12-04 03:13:34 -08003005/* Case open detection */
3006
3007static ssize_t
3008clear_caseopen(struct device *dev, struct device_attribute *attr,
3009 const char *buf, size_t count)
3010{
3011 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003012 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
3013 unsigned long val;
3014 u8 reg;
3015 int ret;
3016
3017 if (kstrtoul(buf, 10, &val) || val != 0)
3018 return -EINVAL;
3019
3020 mutex_lock(&data->update_lock);
3021
3022 /*
3023 * Use CR registers to clear caseopen status.
3024 * The CR registers are the same for all chips, and not all chips
3025 * support clearing the caseopen status through "regular" registers.
3026 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003027 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003028 if (ret) {
3029 count = ret;
3030 goto error;
3031 }
3032
Guenter Roeckdf612d52013-07-08 13:15:04 -07003033 superio_select(data->sioreg, NCT6775_LD_ACPI);
3034 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003035 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003036 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003037 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003038 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3039 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003040
3041 data->valid = false; /* Force cache refresh */
3042error:
3043 mutex_unlock(&data->update_lock);
3044 return count;
3045}
3046
Guenter Roeckf73cf632013-03-18 09:22:50 -07003047static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3048 clear_caseopen, INTRUSION_ALARM_BASE);
3049static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3050 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003051static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3052 store_beep, INTRUSION_ALARM_BASE);
3053static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3054 store_beep, INTRUSION_ALARM_BASE + 1);
3055static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3056 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003057
3058static umode_t nct6775_other_is_visible(struct kobject *kobj,
3059 struct attribute *attr, int index)
3060{
3061 struct device *dev = container_of(kobj, struct device, kobj);
3062 struct nct6775_data *data = dev_get_drvdata(dev);
3063
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003064 if (index == 0 && !data->have_vid)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003065 return 0;
3066
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003067 if (index == 1 || index == 2) {
3068 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003069 return 0;
3070 }
3071
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003072 if (index == 3 || index == 4) {
3073 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
Guenter Roeck30846992013-06-24 22:21:59 -07003074 return 0;
3075 }
3076
Guenter Roeckf73cf632013-03-18 09:22:50 -07003077 return attr->mode;
3078}
3079
3080/*
3081 * nct6775_other_is_visible uses the index into the following array
3082 * to determine if attributes should be created or not.
3083 * Any change in order or content must be matched.
3084 */
3085static struct attribute *nct6775_attributes_other[] = {
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003086 &dev_attr_cpu0_vid.attr, /* 0 */
3087 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
3088 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
3089 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
3090 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
3091 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003092
3093 NULL
3094};
3095
3096static const struct attribute_group nct6775_group_other = {
3097 .attrs = nct6775_attributes_other,
3098 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003099};
3100
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003101static inline void nct6775_init_device(struct nct6775_data *data)
3102{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003103 int i;
3104 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003105
3106 /* Start monitoring if needed */
3107 if (data->REG_CONFIG) {
3108 tmp = nct6775_read_value(data, data->REG_CONFIG);
3109 if (!(tmp & 0x01))
3110 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3111 }
3112
Guenter Roeckaa136e52012-12-04 03:26:05 -08003113 /* Enable temperature sensors if needed */
3114 for (i = 0; i < NUM_TEMP; i++) {
3115 if (!(data->have_temp & (1 << i)))
3116 continue;
3117 if (!data->reg_temp_config[i])
3118 continue;
3119 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3120 if (tmp & 0x01)
3121 nct6775_write_value(data, data->reg_temp_config[i],
3122 tmp & 0xfe);
3123 }
3124
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003125 /* Enable VBAT monitoring if needed */
3126 tmp = nct6775_read_value(data, data->REG_VBAT);
3127 if (!(tmp & 0x01))
3128 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003129
3130 diode = nct6775_read_value(data, data->REG_DIODE);
3131
3132 for (i = 0; i < data->temp_fixed_num; i++) {
3133 if (!(data->have_temp_fixed & (1 << i)))
3134 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003135 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3136 data->temp_type[i]
3137 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003138 else /* thermistor */
3139 data->temp_type[i] = 4;
3140 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003141}
3142
Guenter Roeckf73cf632013-03-18 09:22:50 -07003143static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003144nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003145{
David Bartley578ab5f2013-06-24 22:28:28 -07003146 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3147 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003148 int sioreg = data->sioreg;
3149 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003150
3151 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3152 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003153 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003154
3155 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003156 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003157
3158 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003159 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003160 fan4min = false;
3161 fan5pin = false;
3162 fan6pin = false;
3163 pwm4pin = false;
3164 pwm5pin = false;
3165 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003166 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003167 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003168
Guenter Roeckdf612d52013-07-08 13:15:04 -07003169 superio_select(sioreg, NCT6775_LD_HWM);
3170 regval = superio_inb(sioreg, SIO_REG_ENABLE);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003171
3172 if (regval & 0x80)
3173 fan3pin = gpok;
3174 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003175 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003176
3177 if (regval & 0x40)
3178 fan4pin = gpok;
3179 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003180 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003181
3182 if (regval & 0x20)
3183 fan5pin = gpok;
3184 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003185 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003186
3187 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003188 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003189 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003190 pwm4pin = false;
3191 pwm5pin = false;
3192 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003193 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003194 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003195 fan3pin = !(regval & 0x80);
3196 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003197
3198 fan4pin = false;
3199 fan4min = false;
3200 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003201 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003202 pwm4pin = false;
3203 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003204 pwm6pin = false;
3205 } else { /* NCT6779D or NCT6791D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003206 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003207
3208 fan3pin = !(regval & (1 << 5));
3209 fan4pin = !(regval & (1 << 6));
3210 fan5pin = !(regval & (1 << 7));
3211
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003212 pwm3pin = !(regval & (1 << 0));
3213 pwm4pin = !(regval & (1 << 1));
3214 pwm5pin = !(regval & (1 << 2));
3215
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003216 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003217
3218 if (data->kind == nct6791) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003219 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003220 fan6pin = (regval & (1 << 1));
3221 pwm6pin = (regval & (1 << 0));
3222 } else { /* NCT6779D */
3223 fan6pin = false;
3224 pwm6pin = false;
3225 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003226 }
3227
David Bartley578ab5f2013-06-24 22:28:28 -07003228 /* fan 1 and 2 (0x03) are always present */
3229 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3230 (fan5pin << 4) | (fan6pin << 5);
3231 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3232 (fan5pin << 4);
3233 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3234 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003235}
3236
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003237static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3238 int *available, int *mask)
3239{
3240 int i;
3241 u8 src;
3242
3243 for (i = 0; i < data->pwm_num && *available; i++) {
3244 int index;
3245
3246 if (!regp[i])
3247 continue;
3248 src = nct6775_read_value(data, regp[i]);
3249 src &= 0x1f;
3250 if (!src || (*mask & (1 << src)))
3251 continue;
3252 if (src >= data->temp_label_num ||
3253 !strlen(data->temp_label[src]))
3254 continue;
3255
3256 index = __ffs(*available);
3257 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3258 *available &= ~(1 << index);
3259 *mask |= 1 << src;
3260 }
3261}
3262
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003263static int nct6775_probe(struct platform_device *pdev)
3264{
3265 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003266 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003267 struct nct6775_data *data;
3268 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003269 int i, s, err = 0;
3270 int src, mask, available;
3271 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003272 const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003273 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003274 int num_reg_temp, num_reg_temp_mon;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003275 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003276 struct attribute_group *group;
Guenter Roecka150d952013-07-11 22:55:22 -07003277 struct device *hwmon_dev;
Axel Lin55bdee62014-07-24 08:59:34 +08003278 int num_attr_groups = 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003279
3280 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3281 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3282 DRVNAME))
3283 return -EBUSY;
3284
3285 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3286 GFP_KERNEL);
3287 if (!data)
3288 return -ENOMEM;
3289
3290 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003291 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003292 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003293 mutex_init(&data->update_lock);
3294 data->name = nct6775_device_names[data->kind];
3295 data->bank = 0xff; /* Force initial bank selection */
3296 platform_set_drvdata(pdev, data);
3297
3298 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003299 case nct6106:
3300 data->in_num = 9;
3301 data->pwm_num = 3;
3302 data->auto_pwm_num = 4;
3303 data->temp_fixed_num = 3;
3304 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003305 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003306
3307 data->fan_from_reg = fan_from_reg13;
3308 data->fan_from_reg_min = fan_from_reg13;
3309
3310 data->temp_label = nct6776_temp_label;
3311 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3312
3313 data->REG_VBAT = NCT6106_REG_VBAT;
3314 data->REG_DIODE = NCT6106_REG_DIODE;
3315 data->DIODE_MASK = NCT6106_DIODE_MASK;
3316 data->REG_VIN = NCT6106_REG_IN;
3317 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3318 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3319 data->REG_TARGET = NCT6106_REG_TARGET;
3320 data->REG_FAN = NCT6106_REG_FAN;
3321 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3322 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3323 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3324 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3325 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3326 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3327 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3328 data->REG_PWM[0] = NCT6106_REG_PWM;
3329 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3330 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3331 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3332 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3333 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3334 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3335 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3336 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3337 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3338 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3339 data->REG_CRITICAL_TEMP_TOLERANCE
3340 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3341 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3342 data->CRITICAL_PWM_ENABLE_MASK
3343 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3344 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3345 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3346 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3347 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3348 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3349 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3350 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3351 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3352 data->REG_ALARM = NCT6106_REG_ALARM;
3353 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003354 data->REG_BEEP = NCT6106_REG_BEEP;
3355 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003356
3357 reg_temp = NCT6106_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003358 reg_temp_mon = NCT6106_REG_TEMP_MON;
Guenter Roeck6c009502012-07-01 08:23:15 -07003359 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003360 num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
Guenter Roeck6c009502012-07-01 08:23:15 -07003361 reg_temp_over = NCT6106_REG_TEMP_OVER;
3362 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3363 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3364 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3365 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003366 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3367 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003368
3369 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003370 case nct6775:
3371 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003372 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003373 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003374 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003375 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003376 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003377 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003378
3379 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003380 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003381
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003382 data->fan_from_reg = fan_from_reg16;
3383 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003384 data->target_temp_mask = 0x7f;
3385 data->tolerance_mask = 0x0f;
3386 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003387
Guenter Roeckaa136e52012-12-04 03:26:05 -08003388 data->temp_label = nct6775_temp_label;
3389 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3390
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003391 data->REG_CONFIG = NCT6775_REG_CONFIG;
3392 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003393 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003394 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003395 data->REG_VIN = NCT6775_REG_IN;
3396 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3397 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003398 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003399 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003400 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003401 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003402 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003403 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003404 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3405 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3406 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003407 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003408 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3409 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3410 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3411 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003412 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003413 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3414 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3415 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003416 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3417 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3418 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3419 data->REG_CRITICAL_TEMP_TOLERANCE
3420 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003421 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3422 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003423 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003424 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3425 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3426 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3427 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003428 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003429 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003430
3431 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003432 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003433 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003434 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003435 reg_temp_over = NCT6775_REG_TEMP_OVER;
3436 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3437 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3438 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3439 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3440
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003441 break;
3442 case nct6776:
3443 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003444 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003445 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003446 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003447 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003448 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003449 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003450
3451 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003452 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003453
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003454 data->fan_from_reg = fan_from_reg13;
3455 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003456 data->target_temp_mask = 0xff;
3457 data->tolerance_mask = 0x07;
3458 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003459
Guenter Roeckaa136e52012-12-04 03:26:05 -08003460 data->temp_label = nct6776_temp_label;
3461 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3462
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003463 data->REG_CONFIG = NCT6775_REG_CONFIG;
3464 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003465 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003466 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003467 data->REG_VIN = NCT6775_REG_IN;
3468 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3469 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003470 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003471 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003472 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003473 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003474 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003475 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003476 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3477 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3478 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3479 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003480 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003481 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3482 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003483 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3484 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003485 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3486 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3487 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003488 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3489 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3490 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3491 data->REG_CRITICAL_TEMP_TOLERANCE
3492 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003493 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3494 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003495 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003496 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3497 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3498 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3499 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003500 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003501 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003502
3503 reg_temp = NCT6775_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003504 reg_temp_mon = NCT6775_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003505 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003506 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003507 reg_temp_over = NCT6775_REG_TEMP_OVER;
3508 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3509 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3510 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3511 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3512
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003513 break;
3514 case nct6779:
3515 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003516 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003517 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003518 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003519 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003520 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003521 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003522
3523 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003524 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003525
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003526 data->fan_from_reg = fan_from_reg13;
3527 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003528 data->target_temp_mask = 0xff;
3529 data->tolerance_mask = 0x07;
3530 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003531
Guenter Roeckaa136e52012-12-04 03:26:05 -08003532 data->temp_label = nct6779_temp_label;
3533 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3534
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003535 data->REG_CONFIG = NCT6775_REG_CONFIG;
3536 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003537 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003538 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003539 data->REG_VIN = NCT6779_REG_IN;
3540 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3541 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003542 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003543 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003544 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003545 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003546 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003547 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003548 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3549 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3550 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3551 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003552 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003553 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3554 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003555 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3556 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003557 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3558 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3559 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003560 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3561 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3562 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3563 data->REG_CRITICAL_TEMP_TOLERANCE
3564 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003565 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3566 data->CRITICAL_PWM_ENABLE_MASK
3567 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3568 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003569 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3570 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003571 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003572 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3573 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3574 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3575 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003576 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003577 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003578
3579 reg_temp = NCT6779_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003580 reg_temp_mon = NCT6779_REG_TEMP_MON;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003581 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003582 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003583 reg_temp_over = NCT6779_REG_TEMP_OVER;
3584 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3585 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3586 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3587 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3588
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003589 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003590 case nct6791:
3591 data->in_num = 15;
3592 data->pwm_num = 6;
3593 data->auto_pwm_num = 4;
3594 data->has_fan_div = false;
3595 data->temp_fixed_num = 6;
3596 data->num_temp_alarms = 2;
3597 data->num_temp_beeps = 2;
3598
3599 data->ALARM_BITS = NCT6791_ALARM_BITS;
3600 data->BEEP_BITS = NCT6779_BEEP_BITS;
3601
3602 data->fan_from_reg = fan_from_reg13;
3603 data->fan_from_reg_min = fan_from_reg13;
3604 data->target_temp_mask = 0xff;
3605 data->tolerance_mask = 0x07;
3606 data->speed_tolerance_limit = 63;
3607
3608 data->temp_label = nct6779_temp_label;
3609 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3610
3611 data->REG_CONFIG = NCT6775_REG_CONFIG;
3612 data->REG_VBAT = NCT6775_REG_VBAT;
3613 data->REG_DIODE = NCT6775_REG_DIODE;
3614 data->DIODE_MASK = NCT6775_DIODE_MASK;
3615 data->REG_VIN = NCT6779_REG_IN;
3616 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3617 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3618 data->REG_TARGET = NCT6775_REG_TARGET;
3619 data->REG_FAN = NCT6779_REG_FAN;
3620 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3621 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3622 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3623 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3624 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3625 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3626 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3627 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3628 data->REG_PWM[0] = NCT6775_REG_PWM;
3629 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3630 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003631 data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
3632 data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
David Bartley578ab5f2013-06-24 22:28:28 -07003633 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3634 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3635 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3636 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3637 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3638 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3639 data->REG_CRITICAL_TEMP_TOLERANCE
3640 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3641 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3642 data->CRITICAL_PWM_ENABLE_MASK
3643 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3644 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3645 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3646 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3647 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckcc76dee2013-11-13 12:47:17 -08003648 data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
3649 data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
3650 data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
3651 data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
David Bartley578ab5f2013-06-24 22:28:28 -07003652 data->REG_ALARM = NCT6791_REG_ALARM;
3653 data->REG_BEEP = NCT6776_REG_BEEP;
3654
3655 reg_temp = NCT6779_REG_TEMP;
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003656 reg_temp_mon = NCT6779_REG_TEMP_MON;
David Bartley578ab5f2013-06-24 22:28:28 -07003657 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003658 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
David Bartley578ab5f2013-06-24 22:28:28 -07003659 reg_temp_over = NCT6779_REG_TEMP_OVER;
3660 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3661 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3662 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3663 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3664
3665 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003666 default:
3667 return -ENODEV;
3668 }
3669 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003670 data->have_temp = 0;
3671
3672 /*
3673 * On some boards, not all available temperature sources are monitored,
3674 * even though some of the monitoring registers are unused.
3675 * Get list of unused monitoring registers, then detect if any fan
3676 * controls are configured to use unmonitored temperature sources.
3677 * If so, assign the unmonitored temperature sources to available
3678 * monitoring registers.
3679 */
3680 mask = 0;
3681 available = 0;
3682 for (i = 0; i < num_reg_temp; i++) {
3683 if (reg_temp[i] == 0)
3684 continue;
3685
3686 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3687 if (!src || (mask & (1 << src)))
3688 available |= 1 << i;
3689
3690 mask |= 1 << src;
3691 }
3692
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003693 /*
3694 * Now find unmonitored temperature registers and enable monitoring
3695 * if additional monitoring registers are available.
3696 */
3697 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3698 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3699
Guenter Roeckaa136e52012-12-04 03:26:05 -08003700 mask = 0;
3701 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3702 for (i = 0; i < num_reg_temp; i++) {
3703 if (reg_temp[i] == 0)
3704 continue;
3705
3706 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3707 if (!src || (mask & (1 << src)))
3708 continue;
3709
3710 if (src >= data->temp_label_num ||
3711 !strlen(data->temp_label[src])) {
3712 dev_info(dev,
3713 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3714 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3715 continue;
3716 }
3717
3718 mask |= 1 << src;
3719
3720 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3721 if (src <= data->temp_fixed_num) {
3722 data->have_temp |= 1 << (src - 1);
3723 data->have_temp_fixed |= 1 << (src - 1);
3724 data->reg_temp[0][src - 1] = reg_temp[i];
3725 data->reg_temp[1][src - 1] = reg_temp_over[i];
3726 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003727 if (reg_temp_crit_h && reg_temp_crit_h[i])
3728 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3729 else if (reg_temp_crit[src - 1])
3730 data->reg_temp[3][src - 1]
3731 = reg_temp_crit[src - 1];
3732 if (reg_temp_crit_l && reg_temp_crit_l[i])
3733 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003734 data->reg_temp_config[src - 1] = reg_temp_config[i];
3735 data->temp_src[src - 1] = src;
3736 continue;
3737 }
3738
3739 if (s >= NUM_TEMP)
3740 continue;
3741
3742 /* Use dynamic index for other sources */
3743 data->have_temp |= 1 << s;
3744 data->reg_temp[0][s] = reg_temp[i];
3745 data->reg_temp[1][s] = reg_temp_over[i];
3746 data->reg_temp[2][s] = reg_temp_hyst[i];
3747 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003748 if (reg_temp_crit_h && reg_temp_crit_h[i])
3749 data->reg_temp[3][s] = reg_temp_crit_h[i];
3750 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003751 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003752 if (reg_temp_crit_l && reg_temp_crit_l[i])
3753 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003754
3755 data->temp_src[s] = src;
3756 s++;
3757 }
3758
Guenter Roeckd1a284b2013-11-13 12:46:20 -08003759 /*
3760 * Repeat with temperatures used for fan control.
3761 * This set of registers does not support limits.
3762 */
3763 for (i = 0; i < num_reg_temp_mon; i++) {
3764 if (reg_temp_mon[i] == 0)
3765 continue;
3766
3767 src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f;
3768 if (!src || (mask & (1 << src)))
3769 continue;
3770
3771 if (src >= data->temp_label_num ||
3772 !strlen(data->temp_label[src])) {
3773 dev_info(dev,
3774 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3775 src, i, data->REG_TEMP_SEL[i],
3776 reg_temp_mon[i]);
3777 continue;
3778 }
3779
3780 mask |= 1 << src;
3781
3782 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3783 if (src <= data->temp_fixed_num) {
3784 if (data->have_temp & (1 << (src - 1)))
3785 continue;
3786 data->have_temp |= 1 << (src - 1);
3787 data->have_temp_fixed |= 1 << (src - 1);
3788 data->reg_temp[0][src - 1] = reg_temp_mon[i];
3789 data->temp_src[src - 1] = src;
3790 continue;
3791 }
3792
3793 if (s >= NUM_TEMP)
3794 continue;
3795
3796 /* Use dynamic index for other sources */
3797 data->have_temp |= 1 << s;
3798 data->reg_temp[0][s] = reg_temp_mon[i];
3799 data->temp_src[s] = src;
3800 s++;
3801 }
3802
Guenter Roeckaa136e52012-12-04 03:26:05 -08003803#ifdef USE_ALTERNATE
3804 /*
3805 * Go through the list of alternate temp registers and enable
3806 * if possible.
3807 * The temperature is already monitored if the respective bit in <mask>
3808 * is set.
3809 */
3810 for (i = 0; i < data->temp_label_num - 1; i++) {
3811 if (!reg_temp_alternate[i])
3812 continue;
3813 if (mask & (1 << (i + 1)))
3814 continue;
3815 if (i < data->temp_fixed_num) {
3816 if (data->have_temp & (1 << i))
3817 continue;
3818 data->have_temp |= 1 << i;
3819 data->have_temp_fixed |= 1 << i;
3820 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003821 if (i < num_reg_temp) {
3822 data->reg_temp[1][i] = reg_temp_over[i];
3823 data->reg_temp[2][i] = reg_temp_hyst[i];
3824 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003825 data->temp_src[i] = i + 1;
3826 continue;
3827 }
3828
3829 if (s >= NUM_TEMP) /* Abort if no more space */
3830 break;
3831
3832 data->have_temp |= 1 << s;
3833 data->reg_temp[0][s] = reg_temp_alternate[i];
3834 data->temp_src[s] = i + 1;
3835 s++;
3836 }
3837#endif /* USE_ALTERNATE */
3838
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003839 /* Initialize the chip */
3840 nct6775_init_device(data);
3841
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003842 err = superio_enter(sio_data->sioreg);
3843 if (err)
3844 return err;
3845
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003846 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3847 switch (data->kind) {
3848 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003849 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003850 break;
3851 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003852 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003853 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003854 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003855 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003856 case nct6791:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003857 break;
3858 }
3859
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003860 /*
3861 * Read VID value
3862 * We can get the VID input values directly at logical device D 0xe3.
3863 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003864 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003865 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3866 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3867 data->vrm = vid_which_vrm();
3868 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003869
3870 if (fan_debounce) {
3871 u8 tmp;
3872
3873 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3874 tmp = superio_inb(sio_data->sioreg,
3875 NCT6775_REG_CR_FAN_DEBOUNCE);
3876 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003877 case nct6106:
3878 tmp |= 0xe0;
3879 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003880 case nct6775:
3881 tmp |= 0x1e;
3882 break;
3883 case nct6776:
3884 case nct6779:
3885 tmp |= 0x3e;
3886 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003887 case nct6791:
3888 tmp |= 0x7e;
3889 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003890 }
3891 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3892 tmp);
3893 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3894 data->name);
3895 }
3896
Guenter Roeckdf612d52013-07-08 13:15:04 -07003897 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003898
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003899 superio_exit(sio_data->sioreg);
3900
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003901 /* Read fan clock dividers immediately */
3902 nct6775_init_fan_common(dev, data);
3903
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003904 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003905 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3906 data->pwm_num);
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003907 if (IS_ERR(group))
3908 return PTR_ERR(group);
3909
Axel Lin55bdee62014-07-24 08:59:34 +08003910 data->groups[num_attr_groups++] = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003911
Guenter Roeckf73cf632013-03-18 09:22:50 -07003912 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3913 fls(data->have_in));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003914 if (IS_ERR(group))
3915 return PTR_ERR(group);
3916
Axel Lin55bdee62014-07-24 08:59:34 +08003917 data->groups[num_attr_groups++] = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003918
Guenter Roeckf73cf632013-03-18 09:22:50 -07003919 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3920 fls(data->has_fan));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003921 if (IS_ERR(group))
3922 return PTR_ERR(group);
3923
Axel Lin55bdee62014-07-24 08:59:34 +08003924 data->groups[num_attr_groups++] = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003925
Guenter Roeckf73cf632013-03-18 09:22:50 -07003926 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3927 fls(data->have_temp));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003928 if (IS_ERR(group))
3929 return PTR_ERR(group);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003930
Axel Lin55bdee62014-07-24 08:59:34 +08003931 data->groups[num_attr_groups++] = group;
3932 data->groups[num_attr_groups++] = &nct6775_group_other;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003933
Guenter Roecka150d952013-07-11 22:55:22 -07003934 hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
3935 data, data->groups);
Fengguang Wu9c09bd82013-09-17 06:43:42 -07003936 return PTR_ERR_OR_ZERO(hwmon_dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003937}
3938
Guenter Roeckf5776cc2013-12-25 07:25:59 -08003939static void nct6791_enable_io_mapping(int sioaddr)
3940{
3941 int val;
3942
3943 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
3944 if (val & 0x10) {
3945 pr_info("Enabling hardware monitor logical device mappings.\n");
3946 superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
3947 val & ~0x10);
3948 }
3949}
3950
Guenter Roeck84d19d92012-12-04 08:01:39 -08003951#ifdef CONFIG_PM
3952static int nct6775_suspend(struct device *dev)
3953{
3954 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003955
3956 mutex_lock(&data->update_lock);
3957 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003958 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003959 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3960 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3961 }
3962 mutex_unlock(&data->update_lock);
3963
3964 return 0;
3965}
3966
3967static int nct6775_resume(struct device *dev)
3968{
3969 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckf5776cc2013-12-25 07:25:59 -08003970 int i, j, err = 0;
Guenter Roeck84d19d92012-12-04 08:01:39 -08003971
3972 mutex_lock(&data->update_lock);
3973 data->bank = 0xff; /* Force initial bank selection */
3974
Guenter Roeckf5776cc2013-12-25 07:25:59 -08003975 if (data->kind == nct6791) {
3976 err = superio_enter(data->sioreg);
3977 if (err)
3978 goto abort;
3979
3980 nct6791_enable_io_mapping(data->sioreg);
3981 superio_exit(data->sioreg);
3982 }
3983
Guenter Roeck84d19d92012-12-04 08:01:39 -08003984 /* Restore limits */
3985 for (i = 0; i < data->in_num; i++) {
3986 if (!(data->have_in & (1 << i)))
3987 continue;
3988
3989 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3990 data->in[i][1]);
3991 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3992 data->in[i][2]);
3993 }
3994
Guenter Roeckc409fd42013-04-09 05:04:00 -07003995 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003996 if (!(data->has_fan_min & (1 << i)))
3997 continue;
3998
3999 nct6775_write_value(data, data->REG_FAN_MIN[i],
4000 data->fan_min[i]);
4001 }
4002
4003 for (i = 0; i < NUM_TEMP; i++) {
4004 if (!(data->have_temp & (1 << i)))
4005 continue;
4006
Guenter Roeckc409fd42013-04-09 05:04:00 -07004007 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08004008 if (data->reg_temp[j][i])
4009 nct6775_write_temp(data, data->reg_temp[j][i],
4010 data->temp[j][i]);
4011 }
4012
4013 /* Restore other settings */
4014 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07004015 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08004016 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
4017 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
4018 }
4019
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004020abort:
Guenter Roeck84d19d92012-12-04 08:01:39 -08004021 /* Force re-reading all values */
4022 data->valid = false;
4023 mutex_unlock(&data->update_lock);
4024
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004025 return err;
Guenter Roeck84d19d92012-12-04 08:01:39 -08004026}
4027
4028static const struct dev_pm_ops nct6775_dev_pm_ops = {
4029 .suspend = nct6775_suspend,
4030 .resume = nct6775_resume,
Harald Judt374d1f92013-07-30 19:50:16 +02004031 .freeze = nct6775_suspend,
4032 .restore = nct6775_resume,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004033};
4034
4035#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
4036#else
4037#define NCT6775_DEV_PM_OPS NULL
4038#endif /* CONFIG_PM */
4039
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004040static struct platform_driver nct6775_driver = {
4041 .driver = {
4042 .owner = THIS_MODULE,
4043 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08004044 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004045 },
4046 .probe = nct6775_probe,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004047};
4048
Guenter Roeck6d4b3622013-04-21 09:08:11 -07004049static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07004050 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004051 "NCT6775F",
4052 "NCT6776D/F",
4053 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07004054 "NCT6791D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07004055};
4056
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004057/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004058static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004059{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004060 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004061 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004062 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004063
4064 err = superio_enter(sioaddr);
4065 if (err)
4066 return err;
4067
4068 if (force_id)
4069 val = force_id;
4070 else
4071 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
4072 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
4073 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07004074 case SIO_NCT6106_ID:
4075 sio_data->kind = nct6106;
4076 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004077 case SIO_NCT6775_ID:
4078 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004079 break;
4080 case SIO_NCT6776_ID:
4081 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004082 break;
4083 case SIO_NCT6779_ID:
4084 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004085 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004086 case SIO_NCT6791_ID:
4087 sio_data->kind = nct6791;
4088 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004089 default:
4090 if (val != 0xffff)
4091 pr_debug("unsupported chip ID: 0x%04x\n", val);
4092 superio_exit(sioaddr);
4093 return -ENODEV;
4094 }
4095
4096 /* We have a known chip, find the HWM I/O address */
4097 superio_select(sioaddr, NCT6775_LD_HWM);
4098 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4099 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004100 addr = val & IOREGION_ALIGNMENT;
4101 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004102 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4103 superio_exit(sioaddr);
4104 return -ENODEV;
4105 }
4106
4107 /* Activate logical device if needed */
4108 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4109 if (!(val & 0x01)) {
4110 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4111 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4112 }
Guenter Roeckf5776cc2013-12-25 07:25:59 -08004113
4114 if (sio_data->kind == nct6791)
4115 nct6791_enable_io_mapping(sioaddr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004116
4117 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004118 pr_info("Found %s or compatible chip at %#x:%#x\n",
4119 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004120 sio_data->sioreg = sioaddr;
4121
Guenter Roeck698a7c22013-04-05 07:35:25 -07004122 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004123}
4124
4125/*
4126 * when Super-I/O functions move to a separate file, the Super-I/O
4127 * bus will manage the lifetime of the device and this module will only keep
Guenter Roeck615fc8c2013-07-06 09:43:30 -07004128 * track of the nct6775 driver. But since we use platform_device_alloc(), we
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004129 * must keep track of the device
4130 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004131static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004132
4133static int __init sensors_nct6775_init(void)
4134{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004135 int i, err;
4136 bool found = false;
4137 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004138 struct resource res;
4139 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004140 int sioaddr[2] = { 0x2e, 0x4e };
4141
4142 err = platform_driver_register(&nct6775_driver);
4143 if (err)
4144 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004145
4146 /*
4147 * initialize sio_data->kind and sio_data->sioreg.
4148 *
4149 * when Super-I/O functions move to a separate file, the Super-I/O
4150 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4151 * nct6775 hardware monitor, and call probe()
4152 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004153 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4154 address = nct6775_find(sioaddr[i], &sio_data);
4155 if (address <= 0)
4156 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004157
Guenter Roeck698a7c22013-04-05 07:35:25 -07004158 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004159
Guenter Roeck698a7c22013-04-05 07:35:25 -07004160 pdev[i] = platform_device_alloc(DRVNAME, address);
4161 if (!pdev[i]) {
4162 err = -ENOMEM;
Axel Lin9d311ed2014-05-24 23:21:23 +08004163 goto exit_device_unregister;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004164 }
4165
4166 err = platform_device_add_data(pdev[i], &sio_data,
4167 sizeof(struct nct6775_sio_data));
4168 if (err)
4169 goto exit_device_put;
4170
4171 memset(&res, 0, sizeof(res));
4172 res.name = DRVNAME;
4173 res.start = address + IOREGION_OFFSET;
4174 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4175 res.flags = IORESOURCE_IO;
4176
4177 err = acpi_check_resource_conflict(&res);
4178 if (err) {
4179 platform_device_put(pdev[i]);
4180 pdev[i] = NULL;
4181 continue;
4182 }
4183
4184 err = platform_device_add_resources(pdev[i], &res, 1);
4185 if (err)
4186 goto exit_device_put;
4187
4188 /* platform_device_add calls probe() */
4189 err = platform_device_add(pdev[i]);
4190 if (err)
4191 goto exit_device_put;
4192 }
4193 if (!found) {
4194 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004195 goto exit_unregister;
4196 }
4197
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004198 return 0;
4199
4200exit_device_put:
Axel Lin9d311ed2014-05-24 23:21:23 +08004201 platform_device_put(pdev[i]);
4202exit_device_unregister:
4203 while (--i >= 0) {
Guenter Roeck698a7c22013-04-05 07:35:25 -07004204 if (pdev[i])
Axel Lin9d311ed2014-05-24 23:21:23 +08004205 platform_device_unregister(pdev[i]);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004206 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004207exit_unregister:
4208 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004209 return err;
4210}
4211
4212static void __exit sensors_nct6775_exit(void)
4213{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004214 int i;
4215
4216 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4217 if (pdev[i])
4218 platform_device_unregister(pdev[i]);
4219 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004220 platform_driver_unregister(&nct6775_driver);
4221}
4222
4223MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
Axel Lin78313b92014-07-24 08:58:24 +08004224MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D driver");
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004225MODULE_LICENSE("GPL");
4226
4227module_init(sensors_nct6775_init);
4228module_exit(sensors_nct6775_exit);