blob: 58e9e11ef32a43990c215727696c8210c0e3485b [file] [log] [blame]
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001/*
2 * nct6775 - Driver for the hardware monitoring functionality of
3 * Nuvoton NCT677x Super-I/O chips
4 *
5 * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
6 *
7 * Derived from w83627ehf driver
8 * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org>
9 * Copyright (C) 2006 Yuan Mu (Winbond),
10 * Rudolf Marek <r.marek@assembler.cz>
11 * David Hubbard <david.c.hubbard@gmail.com>
12 * Daniel J Blueman <daniel.blueman@gmail.com>
13 * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
14 *
15 * Shamelessly ripped from the w83627hf driver
16 * Copyright (C) 2003 Mark Studebaker
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 *
33 * Supports the following chips:
34 *
35 * Chip #vin #fan #pwm #temp chip IDs man ID
Guenter Roeck6c009502012-07-01 08:23:15 -070036 * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070037 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
David Bartley578ab5f2013-06-24 22:28:28 -070040 * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070041 *
42 * #temp lists the number of monitored temperature sources (first value) plus
43 * the number of directly connectable temperature sensors (second value).
44 */
45
46#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
47
48#include <linux/module.h>
49#include <linux/init.h>
50#include <linux/slab.h>
51#include <linux/jiffies.h>
52#include <linux/platform_device.h>
53#include <linux/hwmon.h>
54#include <linux/hwmon-sysfs.h>
55#include <linux/hwmon-vid.h>
56#include <linux/err.h>
57#include <linux/mutex.h>
58#include <linux/acpi.h>
59#include <linux/io.h>
60#include "lm75.h"
61
Guenter Roeckaa136e52012-12-04 03:26:05 -080062#define USE_ALTERNATE
63
David Bartley578ab5f2013-06-24 22:28:28 -070064enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791 };
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070065
66/* used to set data->name = nct6775_device_names[data->sio_kind] */
67static const char * const nct6775_device_names[] = {
Guenter Roeck6c009502012-07-01 08:23:15 -070068 "nct6106",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070069 "nct6775",
70 "nct6776",
71 "nct6779",
David Bartley578ab5f2013-06-24 22:28:28 -070072 "nct6791",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070073};
74
75static unsigned short force_id;
76module_param(force_id, ushort, 0);
77MODULE_PARM_DESC(force_id, "Override the detected device ID");
78
Guenter Roeck47ece962012-12-04 07:59:32 -080079static unsigned short fan_debounce;
80module_param(fan_debounce, ushort, 0);
81MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
82
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070083#define DRVNAME "nct6775"
84
85/*
86 * Super-I/O constants and functions
87 */
88
Guenter Roecka6bd5872012-12-04 03:13:34 -080089#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070090#define NCT6775_LD_HWM 0x0b
91#define NCT6775_LD_VID 0x0d
92
93#define SIO_REG_LDSEL 0x07 /* Logical device select */
94#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
95#define SIO_REG_ENABLE 0x30 /* Logical device enable */
96#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
97
Guenter Roeck6c009502012-07-01 08:23:15 -070098#define SIO_NCT6106_ID 0xc450
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070099#define SIO_NCT6775_ID 0xb470
100#define SIO_NCT6776_ID 0xc330
101#define SIO_NCT6779_ID 0xc560
David Bartley578ab5f2013-06-24 22:28:28 -0700102#define SIO_NCT6791_ID 0xc800
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700103#define SIO_ID_MASK 0xFFF0
104
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800105enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
106
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700107static inline void
108superio_outb(int ioreg, int reg, int val)
109{
110 outb(reg, ioreg);
111 outb(val, ioreg + 1);
112}
113
114static inline int
115superio_inb(int ioreg, int reg)
116{
117 outb(reg, ioreg);
118 return inb(ioreg + 1);
119}
120
121static inline void
122superio_select(int ioreg, int ld)
123{
124 outb(SIO_REG_LDSEL, ioreg);
125 outb(ld, ioreg + 1);
126}
127
128static inline int
129superio_enter(int ioreg)
130{
131 /*
132 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
133 */
134 if (!request_muxed_region(ioreg, 2, DRVNAME))
135 return -EBUSY;
136
137 outb(0x87, ioreg);
138 outb(0x87, ioreg);
139
140 return 0;
141}
142
143static inline void
144superio_exit(int ioreg)
145{
146 outb(0xaa, ioreg);
147 outb(0x02, ioreg);
148 outb(0x02, ioreg + 1);
149 release_region(ioreg, 2);
150}
151
152/*
153 * ISA constants
154 */
155
156#define IOREGION_ALIGNMENT (~7)
157#define IOREGION_OFFSET 5
158#define IOREGION_LENGTH 2
159#define ADDR_REG_OFFSET 0
160#define DATA_REG_OFFSET 1
161
162#define NCT6775_REG_BANK 0x4E
163#define NCT6775_REG_CONFIG 0x40
164
165/*
166 * Not currently used:
167 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
168 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
169 * REG_MAN_ID is at port 0x4f
170 * REG_CHIP_ID is at port 0x58
171 */
172
Guenter Roeckaa136e52012-12-04 03:26:05 -0800173#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
174#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
175
Guenter Roeck6c009502012-07-01 08:23:15 -0700176#define NUM_REG_ALARM 7 /* Max number of alarm registers */
Guenter Roeck30846992013-06-24 22:21:59 -0700177#define NUM_REG_BEEP 5 /* Max number of beep registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700178
David Bartley578ab5f2013-06-24 22:28:28 -0700179#define NUM_FAN 6
180
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700181/* Common and NCT6775 specific data */
182
183/* Voltage min/max registers for nr=7..14 are in bank 5 */
184
185static const u16 NCT6775_REG_IN_MAX[] = {
186 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
187 0x55c, 0x55e, 0x560, 0x562 };
188static const u16 NCT6775_REG_IN_MIN[] = {
189 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
190 0x55d, 0x55f, 0x561, 0x563 };
191static const u16 NCT6775_REG_IN[] = {
192 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
193};
194
195#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800196#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700197#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700198
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800199#define NCT6775_REG_FANDIV1 0x506
200#define NCT6775_REG_FANDIV2 0x507
201
Guenter Roeck47ece962012-12-04 07:59:32 -0800202#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
203
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700204static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
205
Guenter Roeck30846992013-06-24 22:21:59 -0700206/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700207
208static const s8 NCT6775_ALARM_BITS[] = {
209 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
210 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
211 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700212 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700213 -1, -1, -1, /* unused */
214 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
215 12, -1 }; /* intrusion0, intrusion1 */
216
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800217#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800218#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800219#define INTRUSION_ALARM_BASE 30
220
Guenter Roeck30846992013-06-24 22:21:59 -0700221static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
222
223/*
224 * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
225 * 30..31 intrusion
226 */
227static const s8 NCT6775_BEEP_BITS[] = {
228 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
229 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
230 21, /* global beep enable */
231 6, 7, 11, 28, -1, /* fan1..fan5 */
232 -1, -1, -1, /* unused */
233 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
234 12, -1 }; /* intrusion0, intrusion1 */
235
236#define BEEP_ENABLE_BASE 15
237
Guenter Roecka6bd5872012-12-04 03:13:34 -0800238static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
239static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
240
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800241/* DC or PWM output fan configuration */
242static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
243static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
244
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800245/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800246
David Bartley578ab5f2013-06-24 22:28:28 -0700247static const u16 NCT6775_REG_TARGET[] = {
248 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
249static const u16 NCT6775_REG_FAN_MODE[] = {
250 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800251static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700252 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800253static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700254 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800255static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700256 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
257static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
258 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800259static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
260static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
261
262static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700263 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
264static const u16 NCT6775_REG_PWM[] = {
265 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
266static const u16 NCT6775_REG_PWM_READ[] = {
267 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800268
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800269static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
270static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800271static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
David Bartley578ab5f2013-06-24 22:28:28 -0700272static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800273
Guenter Roeckaa136e52012-12-04 03:26:05 -0800274static const u16 NCT6775_REG_TEMP[] = {
275 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
276
277static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
278 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
279static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
280 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
281static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
282 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
283
284static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
285 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
286
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800287static const u16 NCT6775_REG_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700288 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800289
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800290static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700291 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800292static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700293 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800294static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700295 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800296static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700297 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800298static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700299 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800300
Guenter Roeckaa136e52012-12-04 03:26:05 -0800301static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
302
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800303static const u16 NCT6775_REG_AUTO_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700304 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800305static const u16 NCT6775_REG_AUTO_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700306 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800307
308#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
309#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
310
311static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
312
313static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700314 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800315static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700316 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800317
Guenter Roeckaa136e52012-12-04 03:26:05 -0800318static const char *const nct6775_temp_label[] = {
319 "",
320 "SYSTIN",
321 "CPUTIN",
322 "AUXTIN",
323 "AMD SB-TSI",
324 "PECI Agent 0",
325 "PECI Agent 1",
326 "PECI Agent 2",
327 "PECI Agent 3",
328 "PECI Agent 4",
329 "PECI Agent 5",
330 "PECI Agent 6",
331 "PECI Agent 7",
332 "PCH_CHIP_CPU_MAX_TEMP",
333 "PCH_CHIP_TEMP",
334 "PCH_CPU_TEMP",
335 "PCH_MCH_TEMP",
336 "PCH_DIM0_TEMP",
337 "PCH_DIM1_TEMP",
338 "PCH_DIM2_TEMP",
339 "PCH_DIM3_TEMP"
340};
341
342static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
343 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
344
345static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
346 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
347 0xa07 };
348
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700349/* NCT6776 specific data */
350
351static const s8 NCT6776_ALARM_BITS[] = {
352 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
353 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
354 -1, /* unused */
355 6, 7, 11, 10, 23, /* fan1..fan5 */
356 -1, -1, -1, /* unused */
357 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
358 12, 9 }; /* intrusion0, intrusion1 */
359
Guenter Roeck30846992013-06-24 22:21:59 -0700360static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
361
362static const s8 NCT6776_BEEP_BITS[] = {
363 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
364 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
365 24, /* global beep enable */
366 25, 26, 27, 28, 29, /* fan1..fan5 */
367 -1, -1, -1, /* unused */
368 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
369 30, 31 }; /* intrusion0, intrusion1 */
370
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800371static const u16 NCT6776_REG_TOLERANCE_H[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700372 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800373
David Bartley578ab5f2013-06-24 22:28:28 -0700374static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
375static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800376
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800377static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800378static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800379
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800380static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700381 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800382
Guenter Roeckaa136e52012-12-04 03:26:05 -0800383static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
384 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
385
386static const char *const nct6776_temp_label[] = {
387 "",
388 "SYSTIN",
389 "CPUTIN",
390 "AUXTIN",
391 "SMBUSMASTER 0",
392 "SMBUSMASTER 1",
393 "SMBUSMASTER 2",
394 "SMBUSMASTER 3",
395 "SMBUSMASTER 4",
396 "SMBUSMASTER 5",
397 "SMBUSMASTER 6",
398 "SMBUSMASTER 7",
399 "PECI Agent 0",
400 "PECI Agent 1",
401 "PCH_CHIP_CPU_MAX_TEMP",
402 "PCH_CHIP_TEMP",
403 "PCH_CPU_TEMP",
404 "PCH_MCH_TEMP",
405 "PCH_DIM0_TEMP",
406 "PCH_DIM1_TEMP",
407 "PCH_DIM2_TEMP",
408 "PCH_DIM3_TEMP",
409 "BYTE_TEMP"
410};
411
412static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
413 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
414
415static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
416 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
417
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700418/* NCT6779 specific data */
419
420static const u16 NCT6779_REG_IN[] = {
421 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
422 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
423
424static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
425 0x459, 0x45A, 0x45B, 0x568 };
426
427static const s8 NCT6779_ALARM_BITS[] = {
428 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
429 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
430 -1, /* unused */
431 6, 7, 11, 10, 23, /* fan1..fan5 */
432 -1, -1, -1, /* unused */
433 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
434 12, 9 }; /* intrusion0, intrusion1 */
435
Guenter Roeck30846992013-06-24 22:21:59 -0700436static const s8 NCT6779_BEEP_BITS[] = {
437 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
438 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
439 24, /* global beep enable */
440 25, 26, 27, 28, 29, /* fan1..fan5 */
441 -1, -1, -1, /* unused */
442 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
443 30, 31 }; /* intrusion0, intrusion1 */
444
David Bartley578ab5f2013-06-24 22:28:28 -0700445static const u16 NCT6779_REG_FAN[] = {
446 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800447static const u16 NCT6779_REG_FAN_PULSES[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700448 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800449
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800450static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700451 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700452#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800453static const u16 NCT6779_REG_CRITICAL_PWM[] = {
David Bartley578ab5f2013-06-24 22:28:28 -0700454 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800455
Guenter Roeckaa136e52012-12-04 03:26:05 -0800456static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
457static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
458 0x18, 0x152 };
459static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
460 0x3a, 0x153 };
461static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
462 0x39, 0x155 };
463
464static const u16 NCT6779_REG_TEMP_OFFSET[] = {
465 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
466
467static const char *const nct6779_temp_label[] = {
468 "",
469 "SYSTIN",
470 "CPUTIN",
471 "AUXTIN0",
472 "AUXTIN1",
473 "AUXTIN2",
474 "AUXTIN3",
475 "",
476 "SMBUSMASTER 0",
477 "SMBUSMASTER 1",
478 "SMBUSMASTER 2",
479 "SMBUSMASTER 3",
480 "SMBUSMASTER 4",
481 "SMBUSMASTER 5",
482 "SMBUSMASTER 6",
483 "SMBUSMASTER 7",
484 "PECI Agent 0",
485 "PECI Agent 1",
486 "PCH_CHIP_CPU_MAX_TEMP",
487 "PCH_CHIP_TEMP",
488 "PCH_CPU_TEMP",
489 "PCH_MCH_TEMP",
490 "PCH_DIM0_TEMP",
491 "PCH_DIM1_TEMP",
492 "PCH_DIM2_TEMP",
493 "PCH_DIM3_TEMP",
494 "BYTE_TEMP"
495};
496
497static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
498 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
499 0, 0, 0, 0, 0, 0, 0, 0,
500 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
501 0x408, 0 };
502
503static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
504 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
505
David Bartley578ab5f2013-06-24 22:28:28 -0700506/* NCT6791 specific data */
507
508#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
509
510static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
511 0x459, 0x45A, 0x45B, 0x568, 0x45D };
512
513static const s8 NCT6791_ALARM_BITS[] = {
514 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
515 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
516 -1, /* unused */
517 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
518 -1, -1, /* unused */
519 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
520 12, 9 }; /* intrusion0, intrusion1 */
521
522
Guenter Roeck6c009502012-07-01 08:23:15 -0700523/* NCT6102D/NCT6106D specific data */
524
525#define NCT6106_REG_VBAT 0x318
526#define NCT6106_REG_DIODE 0x319
527#define NCT6106_DIODE_MASK 0x01
528
529static const u16 NCT6106_REG_IN_MAX[] = {
530 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
531static const u16 NCT6106_REG_IN_MIN[] = {
532 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
533static const u16 NCT6106_REG_IN[] = {
534 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
535
536static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
537static const u16 NCT6106_REG_TEMP_HYST[] = {
538 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
539static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700540 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
541static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
542 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
543static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
544 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700545static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
546static const u16 NCT6106_REG_TEMP_CONFIG[] = {
547 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
548
549static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
550static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
551static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
552static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
553
554static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
555static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
556static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
557static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
558static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
559static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
560static const u16 NCT6106_REG_TEMP_SOURCE[] = {
561 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
562
563static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
564static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
565 0x11b, 0x12b, 0x13b };
566
567static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
568#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
569static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
570
571static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
572static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
573static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
574static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
575static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
576static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
577
578static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
579
580static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
581static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
582static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
583static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
584static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
585static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
586
587static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
588static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
589
590static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
591 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
592
593static const s8 NCT6106_ALARM_BITS[] = {
594 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
595 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
596 -1, /* unused */
597 32, 33, 34, -1, -1, /* fan1..fan5 */
598 -1, -1, -1, /* unused */
599 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
600 48, -1 /* intrusion0, intrusion1 */
601};
602
Guenter Roeck30846992013-06-24 22:21:59 -0700603static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
604 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
605
606static const s8 NCT6106_BEEP_BITS[] = {
607 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
608 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
609 32, /* global beep enable */
610 24, 25, 26, 27, 28, /* fan1..fan5 */
611 -1, -1, -1, /* unused */
612 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
613 34, -1 /* intrusion0, intrusion1 */
614};
615
Guenter Roeck6c009502012-07-01 08:23:15 -0700616static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
617 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
618
619static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
620 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
621
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800622static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
623{
624 if (mode == 0 && pwm == 255)
625 return off;
626 return mode + 1;
627}
628
629static int pwm_enable_to_reg(enum pwm_enable mode)
630{
631 if (mode == off)
632 return 0;
633 return mode - 1;
634}
635
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700636/*
637 * Conversions
638 */
639
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800640/* 1 is DC mode, output in ms */
641static unsigned int step_time_from_reg(u8 reg, u8 mode)
642{
643 return mode ? 400 * reg : 100 * reg;
644}
645
646static u8 step_time_to_reg(unsigned int msec, u8 mode)
647{
648 return clamp_val((mode ? (msec + 200) / 400 :
649 (msec + 50) / 100), 1, 255);
650}
651
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800652static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
653{
654 if (reg == 0 || reg == 255)
655 return 0;
656 return 1350000U / (reg << divreg);
657}
658
659static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
660{
661 if ((reg & 0xff1f) == 0xff1f)
662 return 0;
663
664 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
665
666 if (reg == 0)
667 return 0;
668
669 return 1350000U / reg;
670}
671
672static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
673{
674 if (reg == 0 || reg == 0xffff)
675 return 0;
676
677 /*
678 * Even though the registers are 16 bit wide, the fan divisor
679 * still applies.
680 */
681 return 1350000U / (reg << divreg);
682}
683
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800684static u16 fan_to_reg(u32 fan, unsigned int divreg)
685{
686 if (!fan)
687 return 0;
688
689 return (1350000U / fan) >> divreg;
690}
691
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800692static inline unsigned int
693div_from_reg(u8 reg)
694{
695 return 1 << reg;
696}
697
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700698/*
699 * Some of the voltage inputs have internal scaling, the tables below
700 * contain 8 (the ADC LSB in mV) * scaling factor * 100
701 */
702static const u16 scale_in[15] = {
703 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
704 800, 800
705};
706
707static inline long in_from_reg(u8 reg, u8 nr)
708{
709 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
710}
711
712static inline u8 in_to_reg(u32 val, u8 nr)
713{
714 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
715}
716
717/*
718 * Data structures and manipulation thereof
719 */
720
721struct nct6775_data {
722 int addr; /* IO base of hw monitor block */
Guenter Roeckdf612d52013-07-08 13:15:04 -0700723 int sioreg; /* SIO register address */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700724 enum kinds kind;
725 const char *name;
726
727 struct device *hwmon_dev;
Guenter Roeck615fc8c2013-07-06 09:43:30 -0700728
729 int num_attr_groups;
730 const struct attribute_group *groups[6];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700731
Guenter Roeckb7a61352013-04-02 22:14:06 -0700732 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
733 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800734 */
735 u8 temp_src[NUM_TEMP];
736 u16 reg_temp_config[NUM_TEMP];
737 const char * const *temp_label;
738 int temp_label_num;
739
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700740 u16 REG_CONFIG;
741 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800742 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700743 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700744
745 const s8 *ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -0700746 const s8 *BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700747
748 const u16 *REG_VIN;
749 const u16 *REG_IN_MINMAX[2];
750
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800751 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800752 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800753 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800754 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800755 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700756 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800757 const u16 *REG_FAN_TIME[3];
758
759 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800760
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800761 const u8 *REG_PWM_MODE;
762 const u8 *PWM_MODE_MASK;
763
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800764 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
765 * [3]=pwm_max, [4]=pwm_step,
766 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800767 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800768 const u16 *REG_PWM_READ;
769
Guenter Roeck6c009502012-07-01 08:23:15 -0700770 const u16 *REG_CRITICAL_PWM_ENABLE;
771 u8 CRITICAL_PWM_ENABLE_MASK;
772 const u16 *REG_CRITICAL_PWM;
773
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800774 const u16 *REG_AUTO_TEMP;
775 const u16 *REG_AUTO_PWM;
776
777 const u16 *REG_CRITICAL_TEMP;
778 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
779
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800780 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800781 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800782 const u16 *REG_WEIGHT_TEMP_SEL;
783 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
784
Guenter Roeckaa136e52012-12-04 03:26:05 -0800785 const u16 *REG_TEMP_OFFSET;
786
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700787 const u16 *REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -0700788 const u16 *REG_BEEP;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700789
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800790 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
791 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
792
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700793 struct mutex update_lock;
794 bool valid; /* true if following fields are valid */
795 unsigned long last_updated; /* In jiffies */
796
797 /* Register values */
798 u8 bank; /* current register bank */
799 u8 in_num; /* number of in inputs we have */
800 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
David Bartley578ab5f2013-06-24 22:28:28 -0700801 unsigned int rpm[NUM_FAN];
802 u16 fan_min[NUM_FAN];
803 u8 fan_pulses[NUM_FAN];
804 u8 fan_div[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800805 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800806 u8 has_fan; /* some fan inputs can be disabled */
807 u8 has_fan_min; /* some fans don't have min register */
808 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700809
Guenter Roeck6c009502012-07-01 08:23:15 -0700810 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeck30846992013-06-24 22:21:59 -0700811 u8 num_temp_beeps; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800812 u8 temp_fixed_num; /* 3 or 6 */
813 u8 temp_type[NUM_TEMP_FIXED];
814 s8 temp_offset[NUM_TEMP_FIXED];
Dan Carpenterf58876a2013-07-18 18:01:11 +0300815 s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
816 * 3=temp_crit, 4=temp_lcrit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700817 u64 alarms;
Guenter Roeck30846992013-06-24 22:21:59 -0700818 u64 beeps;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700819
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800820 u8 pwm_num; /* number of pwm */
David Bartley578ab5f2013-06-24 22:28:28 -0700821 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
822 * 0->PWM variable duty cycle
823 */
824 enum pwm_enable pwm_enable[NUM_FAN];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800825 /* 0->off
826 * 1->manual
827 * 2->thermal cruise mode (also called SmartFan I)
828 * 3->fan speed cruise mode
829 * 4->SmartFan III
830 * 5->enhanced variable thermal cruise (SmartFan IV)
831 */
David Bartley578ab5f2013-06-24 22:28:28 -0700832 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
833 * [3]=pwm_max, [4]=pwm_step,
834 * [5]=weight_duty_step, [6]=weight_duty_base
835 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800836
David Bartley578ab5f2013-06-24 22:28:28 -0700837 u8 target_temp[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800838 u8 target_temp_mask;
David Bartley578ab5f2013-06-24 22:28:28 -0700839 u32 target_speed[NUM_FAN];
840 u32 target_speed_tolerance[NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800841 u8 speed_tolerance_limit;
842
David Bartley578ab5f2013-06-24 22:28:28 -0700843 u8 temp_tolerance[2][NUM_FAN];
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800844 u8 tolerance_mask;
845
David Bartley578ab5f2013-06-24 22:28:28 -0700846 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800847
848 /* Automatic fan speed control registers */
849 int auto_pwm_num;
David Bartley578ab5f2013-06-24 22:28:28 -0700850 u8 auto_pwm[NUM_FAN][7];
851 u8 auto_temp[NUM_FAN][7];
852 u8 pwm_temp_sel[NUM_FAN];
853 u8 pwm_weight_temp_sel[NUM_FAN];
854 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
855 * 2->temp_base
856 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800857
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700858 u8 vid;
859 u8 vrm;
860
Guenter Roeckf73cf632013-03-18 09:22:50 -0700861 bool have_vid;
862
Guenter Roeckaa136e52012-12-04 03:26:05 -0800863 u16 have_temp;
864 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700865 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800866#ifdef CONFIG_PM
867 /* Remember extra register values over suspend/resume */
868 u8 vbat;
869 u8 fandiv1;
870 u8 fandiv2;
871#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700872};
873
874struct nct6775_sio_data {
875 int sioreg;
876 enum kinds kind;
877};
878
Guenter Roeckf73cf632013-03-18 09:22:50 -0700879struct sensor_device_template {
880 struct device_attribute dev_attr;
881 union {
882 struct {
883 u8 nr;
884 u8 index;
885 } s;
886 int index;
887 } u;
888 bool s2; /* true if both index and nr are used */
889};
890
891struct sensor_device_attr_u {
892 union {
893 struct sensor_device_attribute a1;
894 struct sensor_device_attribute_2 a2;
895 } u;
896 char name[32];
897};
898
899#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
900 .attr = {.name = _template, .mode = _mode }, \
901 .show = _show, \
902 .store = _store, \
903}
904
905#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
906 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
907 .u.index = _index, \
908 .s2 = false }
909
910#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
911 _nr, _index) \
912 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
913 .u.s.index = _index, \
914 .u.s.nr = _nr, \
915 .s2 = true }
916
917#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
918static struct sensor_device_template sensor_dev_template_##_name \
919 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
920 _index)
921
922#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
923 _nr, _index) \
924static struct sensor_device_template sensor_dev_template_##_name \
925 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
926 _nr, _index)
927
928struct sensor_template_group {
929 struct sensor_device_template **templates;
930 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
931 int base;
932};
933
934static struct attribute_group *
935nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
936 int repeat)
937{
938 struct attribute_group *group;
939 struct sensor_device_attr_u *su;
940 struct sensor_device_attribute *a;
941 struct sensor_device_attribute_2 *a2;
942 struct attribute **attrs;
943 struct sensor_device_template **t;
Guenter Roeck615fc8c2013-07-06 09:43:30 -0700944 int i, j, count;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700945
946 if (repeat <= 0)
947 return ERR_PTR(-EINVAL);
948
949 t = tg->templates;
950 for (count = 0; *t; t++, count++)
951 ;
952
953 if (count == 0)
954 return ERR_PTR(-EINVAL);
955
956 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
957 if (group == NULL)
958 return ERR_PTR(-ENOMEM);
959
960 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
961 GFP_KERNEL);
962 if (attrs == NULL)
963 return ERR_PTR(-ENOMEM);
964
965 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
966 GFP_KERNEL);
967 if (su == NULL)
968 return ERR_PTR(-ENOMEM);
969
970 group->attrs = attrs;
971 group->is_visible = tg->is_visible;
972
973 for (i = 0; i < repeat; i++) {
974 t = tg->templates;
975 for (j = 0; *t != NULL; j++) {
976 snprintf(su->name, sizeof(su->name),
977 (*t)->dev_attr.attr.name, tg->base + i);
978 if ((*t)->s2) {
979 a2 = &su->u.a2;
980 a2->dev_attr.attr.name = su->name;
981 a2->nr = (*t)->u.s.nr + i;
982 a2->index = (*t)->u.s.index;
983 a2->dev_attr.attr.mode =
984 (*t)->dev_attr.attr.mode;
985 a2->dev_attr.show = (*t)->dev_attr.show;
986 a2->dev_attr.store = (*t)->dev_attr.store;
987 *attrs = &a2->dev_attr.attr;
988 } else {
989 a = &su->u.a1;
990 a->dev_attr.attr.name = su->name;
991 a->index = (*t)->u.index + i;
992 a->dev_attr.attr.mode =
993 (*t)->dev_attr.attr.mode;
994 a->dev_attr.show = (*t)->dev_attr.show;
995 a->dev_attr.store = (*t)->dev_attr.store;
996 *attrs = &a->dev_attr.attr;
997 }
998 attrs++;
999 su++;
1000 t++;
1001 }
1002 }
1003
Guenter Roeckf73cf632013-03-18 09:22:50 -07001004 return group;
1005}
1006
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001007static bool is_word_sized(struct nct6775_data *data, u16 reg)
1008{
1009 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07001010 case nct6106:
1011 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1012 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1013 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001014 case nct6775:
1015 return (((reg & 0xff00) == 0x100 ||
1016 (reg & 0xff00) == 0x200) &&
1017 ((reg & 0x00ff) == 0x50 ||
1018 (reg & 0x00ff) == 0x53 ||
1019 (reg & 0x00ff) == 0x55)) ||
1020 (reg & 0xfff0) == 0x630 ||
1021 reg == 0x640 || reg == 0x642 ||
1022 reg == 0x662 ||
1023 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1024 reg == 0x73 || reg == 0x75 || reg == 0x77;
1025 case nct6776:
1026 return (((reg & 0xff00) == 0x100 ||
1027 (reg & 0xff00) == 0x200) &&
1028 ((reg & 0x00ff) == 0x50 ||
1029 (reg & 0x00ff) == 0x53 ||
1030 (reg & 0x00ff) == 0x55)) ||
1031 (reg & 0xfff0) == 0x630 ||
1032 reg == 0x402 ||
1033 reg == 0x640 || reg == 0x642 ||
1034 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1035 reg == 0x73 || reg == 0x75 || reg == 0x77;
1036 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001037 case nct6791:
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001038 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
David Bartley578ab5f2013-06-24 22:28:28 -07001039 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001040 reg == 0x402 ||
1041 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1042 reg == 0x640 || reg == 0x642 ||
1043 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
1044 reg == 0x7b;
1045 }
1046 return false;
1047}
1048
1049/*
1050 * On older chips, only registers 0x50-0x5f are banked.
1051 * On more recent chips, all registers are banked.
1052 * Assume that is the case and set the bank number for each access.
1053 * Cache the bank number so it only needs to be set if it changes.
1054 */
1055static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
1056{
1057 u8 bank = reg >> 8;
1058 if (data->bank != bank) {
1059 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
1060 outb_p(bank, data->addr + DATA_REG_OFFSET);
1061 data->bank = bank;
1062 }
1063}
1064
1065static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
1066{
1067 int res, word_sized = is_word_sized(data, reg);
1068
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001069 nct6775_set_bank(data, reg);
1070 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1071 res = inb_p(data->addr + DATA_REG_OFFSET);
1072 if (word_sized) {
1073 outb_p((reg & 0xff) + 1,
1074 data->addr + ADDR_REG_OFFSET);
1075 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
1076 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001077 return res;
1078}
1079
1080static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1081{
1082 int word_sized = is_word_sized(data, reg);
1083
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001084 nct6775_set_bank(data, reg);
1085 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1086 if (word_sized) {
1087 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1088 outb_p((reg & 0xff) + 1,
1089 data->addr + ADDR_REG_OFFSET);
1090 }
1091 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001092 return 0;
1093}
1094
Guenter Roeckaa136e52012-12-04 03:26:05 -08001095/* We left-align 8-bit temperature values to make the code simpler */
1096static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1097{
1098 u16 res;
1099
1100 res = nct6775_read_value(data, reg);
1101 if (!is_word_sized(data, reg))
1102 res <<= 8;
1103
1104 return res;
1105}
1106
1107static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1108{
1109 if (!is_word_sized(data, reg))
1110 value >>= 8;
1111 return nct6775_write_value(data, reg, value);
1112}
1113
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001114/* This function assumes that the caller holds data->update_lock */
1115static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1116{
1117 u8 reg;
1118
1119 switch (nr) {
1120 case 0:
1121 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1122 | (data->fan_div[0] & 0x7);
1123 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1124 break;
1125 case 1:
1126 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1127 | ((data->fan_div[1] << 4) & 0x70);
1128 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1129 break;
1130 case 2:
1131 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1132 | (data->fan_div[2] & 0x7);
1133 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1134 break;
1135 case 3:
1136 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1137 | ((data->fan_div[3] << 4) & 0x70);
1138 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1139 break;
1140 }
1141}
1142
1143static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1144{
1145 if (data->kind == nct6775)
1146 nct6775_write_fan_div(data, nr);
1147}
1148
1149static void nct6775_update_fan_div(struct nct6775_data *data)
1150{
1151 u8 i;
1152
1153 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1154 data->fan_div[0] = i & 0x7;
1155 data->fan_div[1] = (i & 0x70) >> 4;
1156 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1157 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001158 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001159 data->fan_div[3] = (i & 0x70) >> 4;
1160}
1161
1162static void nct6775_update_fan_div_common(struct nct6775_data *data)
1163{
1164 if (data->kind == nct6775)
1165 nct6775_update_fan_div(data);
1166}
1167
1168static void nct6775_init_fan_div(struct nct6775_data *data)
1169{
1170 int i;
1171
1172 nct6775_update_fan_div_common(data);
1173 /*
1174 * For all fans, start with highest divider value if the divider
1175 * register is not initialized. This ensures that we get a
1176 * reading from the fan count register, even if it is not optimal.
1177 * We'll compute a better divider later on.
1178 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001179 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001180 if (!(data->has_fan & (1 << i)))
1181 continue;
1182 if (data->fan_div[i] == 0) {
1183 data->fan_div[i] = 7;
1184 nct6775_write_fan_div_common(data, i);
1185 }
1186 }
1187}
1188
1189static void nct6775_init_fan_common(struct device *dev,
1190 struct nct6775_data *data)
1191{
1192 int i;
1193 u8 reg;
1194
1195 if (data->has_fan_div)
1196 nct6775_init_fan_div(data);
1197
1198 /*
1199 * If fan_min is not set (0), set it to 0xff to disable it. This
1200 * prevents the unnecessary warning when fanX_min is reported as 0.
1201 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001202 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001203 if (data->has_fan_min & (1 << i)) {
1204 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1205 if (!reg)
1206 nct6775_write_value(data, data->REG_FAN_MIN[i],
1207 data->has_fan_div ? 0xff
1208 : 0xff1f);
1209 }
1210 }
1211}
1212
1213static void nct6775_select_fan_div(struct device *dev,
1214 struct nct6775_data *data, int nr, u16 reg)
1215{
1216 u8 fan_div = data->fan_div[nr];
1217 u16 fan_min;
1218
1219 if (!data->has_fan_div)
1220 return;
1221
1222 /*
1223 * If we failed to measure the fan speed, or the reported value is not
1224 * in the optimal range, and the clock divider can be modified,
1225 * let's try that for next time.
1226 */
1227 if (reg == 0x00 && fan_div < 0x07)
1228 fan_div++;
1229 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1230 fan_div--;
1231
1232 if (fan_div != data->fan_div[nr]) {
1233 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1234 nr + 1, div_from_reg(data->fan_div[nr]),
1235 div_from_reg(fan_div));
1236
1237 /* Preserve min limit if possible */
1238 if (data->has_fan_min & (1 << nr)) {
1239 fan_min = data->fan_min[nr];
1240 if (fan_div > data->fan_div[nr]) {
1241 if (fan_min != 255 && fan_min > 1)
1242 fan_min >>= 1;
1243 } else {
1244 if (fan_min != 255) {
1245 fan_min <<= 1;
1246 if (fan_min > 254)
1247 fan_min = 254;
1248 }
1249 }
1250 if (fan_min != data->fan_min[nr]) {
1251 data->fan_min[nr] = fan_min;
1252 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1253 fan_min);
1254 }
1255 }
1256 data->fan_div[nr] = fan_div;
1257 nct6775_write_fan_div_common(data, nr);
1258 }
1259}
1260
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001261static void nct6775_update_pwm(struct device *dev)
1262{
1263 struct nct6775_data *data = dev_get_drvdata(dev);
1264 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001265 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001266 bool duty_is_dc;
1267
1268 for (i = 0; i < data->pwm_num; i++) {
1269 if (!(data->has_pwm & (1 << i)))
1270 continue;
1271
1272 duty_is_dc = data->REG_PWM_MODE[i] &&
1273 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1274 & data->PWM_MODE_MASK[i]);
1275 data->pwm_mode[i] = duty_is_dc;
1276
1277 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1278 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1279 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1280 data->pwm[j][i]
1281 = nct6775_read_value(data,
1282 data->REG_PWM[j][i]);
1283 }
1284 }
1285
1286 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1287 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001288
1289 if (!data->temp_tolerance[0][i] ||
1290 data->pwm_enable[i] != speed_cruise)
1291 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1292 if (!data->target_speed_tolerance[i] ||
1293 data->pwm_enable[i] == speed_cruise) {
1294 u8 t = fanmodecfg & 0x0f;
1295 if (data->REG_TOLERANCE_H) {
1296 t |= (nct6775_read_value(data,
1297 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1298 }
1299 data->target_speed_tolerance[i] = t;
1300 }
1301
1302 data->temp_tolerance[1][i] =
1303 nct6775_read_value(data,
1304 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1305
1306 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1307 data->pwm_temp_sel[i] = reg & 0x1f;
1308 /* If fan can stop, report floor as 0 */
1309 if (reg & 0x80)
1310 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001311
1312 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1313 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1314 /* If weight is disabled, report weight source as 0 */
1315 if (j == 1 && !(reg & 0x80))
1316 data->pwm_weight_temp_sel[i] = 0;
1317
1318 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001319 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001320 data->weight_temp[j][i]
1321 = nct6775_read_value(data,
1322 data->REG_WEIGHT_TEMP[j][i]);
1323 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001324 }
1325}
1326
1327static void nct6775_update_pwm_limits(struct device *dev)
1328{
1329 struct nct6775_data *data = dev_get_drvdata(dev);
1330 int i, j;
1331 u8 reg;
1332 u16 reg_t;
1333
1334 for (i = 0; i < data->pwm_num; i++) {
1335 if (!(data->has_pwm & (1 << i)))
1336 continue;
1337
Guenter Roeckc409fd42013-04-09 05:04:00 -07001338 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001339 data->fan_time[j][i] =
1340 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1341 }
1342
1343 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1344 /* Update only in matching mode or if never updated */
1345 if (!data->target_temp[i] ||
1346 data->pwm_enable[i] == thermal_cruise)
1347 data->target_temp[i] = reg_t & data->target_temp_mask;
1348 if (!data->target_speed[i] ||
1349 data->pwm_enable[i] == speed_cruise) {
1350 if (data->REG_TOLERANCE_H) {
1351 reg_t |= (nct6775_read_value(data,
1352 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1353 }
1354 data->target_speed[i] = reg_t;
1355 }
1356
1357 for (j = 0; j < data->auto_pwm_num; j++) {
1358 data->auto_pwm[i][j] =
1359 nct6775_read_value(data,
1360 NCT6775_AUTO_PWM(data, i, j));
1361 data->auto_temp[i][j] =
1362 nct6775_read_value(data,
1363 NCT6775_AUTO_TEMP(data, i, j));
1364 }
1365
1366 /* critical auto_pwm temperature data */
1367 data->auto_temp[i][data->auto_pwm_num] =
1368 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1369
1370 switch (data->kind) {
1371 case nct6775:
1372 reg = nct6775_read_value(data,
1373 NCT6775_REG_CRITICAL_ENAB[i]);
1374 data->auto_pwm[i][data->auto_pwm_num] =
1375 (reg & 0x02) ? 0xff : 0x00;
1376 break;
1377 case nct6776:
1378 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1379 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001380 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001381 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07001382 case nct6791:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001383 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001384 data->REG_CRITICAL_PWM_ENABLE[i]);
1385 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1386 reg = nct6775_read_value(data,
1387 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001388 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001389 reg = 0xff;
1390 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001391 break;
1392 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001393 }
1394}
1395
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001396static struct nct6775_data *nct6775_update_device(struct device *dev)
1397{
1398 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001399 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001400
1401 mutex_lock(&data->update_lock);
1402
Guenter Roeck6445e662013-04-21 09:13:28 -07001403 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001404 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001405 /* Fan clock dividers */
1406 nct6775_update_fan_div_common(data);
1407
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001408 /* Measured voltages and limits */
1409 for (i = 0; i < data->in_num; i++) {
1410 if (!(data->have_in & (1 << i)))
1411 continue;
1412
1413 data->in[i][0] = nct6775_read_value(data,
1414 data->REG_VIN[i]);
1415 data->in[i][1] = nct6775_read_value(data,
1416 data->REG_IN_MINMAX[0][i]);
1417 data->in[i][2] = nct6775_read_value(data,
1418 data->REG_IN_MINMAX[1][i]);
1419 }
1420
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001421 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001422 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001423 u16 reg;
1424
1425 if (!(data->has_fan & (1 << i)))
1426 continue;
1427
1428 reg = nct6775_read_value(data, data->REG_FAN[i]);
1429 data->rpm[i] = data->fan_from_reg(reg,
1430 data->fan_div[i]);
1431
1432 if (data->has_fan_min & (1 << i))
1433 data->fan_min[i] = nct6775_read_value(data,
1434 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001435 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001436 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1437 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001438
1439 nct6775_select_fan_div(dev, data, i, reg);
1440 }
1441
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001442 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001443 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001444
Guenter Roeckaa136e52012-12-04 03:26:05 -08001445 /* Measured temperatures and limits */
1446 for (i = 0; i < NUM_TEMP; i++) {
1447 if (!(data->have_temp & (1 << i)))
1448 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001449 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001450 if (data->reg_temp[j][i])
1451 data->temp[j][i]
1452 = nct6775_read_temp(data,
1453 data->reg_temp[j][i]);
1454 }
Guenter Roeck45a5b3a2013-09-11 10:35:47 -07001455 if (i >= NUM_TEMP_FIXED ||
1456 !(data->have_temp_fixed & (1 << i)))
Guenter Roeckaa136e52012-12-04 03:26:05 -08001457 continue;
1458 data->temp_offset[i]
1459 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1460 }
1461
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001462 data->alarms = 0;
1463 for (i = 0; i < NUM_REG_ALARM; i++) {
1464 u8 alarm;
1465 if (!data->REG_ALARM[i])
1466 continue;
1467 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1468 data->alarms |= ((u64)alarm) << (i << 3);
1469 }
1470
Guenter Roeck30846992013-06-24 22:21:59 -07001471 data->beeps = 0;
1472 for (i = 0; i < NUM_REG_BEEP; i++) {
1473 u8 beep;
1474 if (!data->REG_BEEP[i])
1475 continue;
1476 beep = nct6775_read_value(data, data->REG_BEEP[i]);
1477 data->beeps |= ((u64)beep) << (i << 3);
1478 }
1479
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001480 data->last_updated = jiffies;
1481 data->valid = true;
1482 }
1483
1484 mutex_unlock(&data->update_lock);
1485 return data;
1486}
1487
1488/*
1489 * Sysfs callback functions
1490 */
1491static ssize_t
1492show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1493{
1494 struct nct6775_data *data = nct6775_update_device(dev);
1495 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1496 int nr = sattr->nr;
1497 int index = sattr->index;
1498 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1499}
1500
1501static ssize_t
1502store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1503 size_t count)
1504{
1505 struct nct6775_data *data = dev_get_drvdata(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 unsigned long val;
1510 int err = kstrtoul(buf, 10, &val);
1511 if (err < 0)
1512 return err;
1513 mutex_lock(&data->update_lock);
1514 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001515 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001516 data->in[nr][index]);
1517 mutex_unlock(&data->update_lock);
1518 return count;
1519}
1520
1521static ssize_t
1522show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1523{
1524 struct nct6775_data *data = nct6775_update_device(dev);
1525 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1526 int nr = data->ALARM_BITS[sattr->index];
1527 return sprintf(buf, "%u\n",
1528 (unsigned int)((data->alarms >> nr) & 0x01));
1529}
1530
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001531static int find_temp_source(struct nct6775_data *data, int index, int count)
1532{
1533 int source = data->temp_src[index];
1534 int nr;
1535
1536 for (nr = 0; nr < count; nr++) {
1537 int src;
1538
1539 src = nct6775_read_value(data,
1540 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1541 if (src == source)
1542 return nr;
1543 }
Guenter Roecke8ab5082013-09-11 10:32:18 -07001544 return -ENODEV;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001545}
1546
1547static ssize_t
1548show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1549{
1550 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1551 struct nct6775_data *data = nct6775_update_device(dev);
1552 unsigned int alarm = 0;
1553 int nr;
1554
1555 /*
1556 * For temperatures, there is no fixed mapping from registers to alarm
1557 * bits. Alarm bits are determined by the temperature source mapping.
1558 */
1559 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1560 if (nr >= 0) {
1561 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1562 alarm = (data->alarms >> bit) & 0x01;
1563 }
1564 return sprintf(buf, "%u\n", alarm);
1565}
1566
Guenter Roeck30846992013-06-24 22:21:59 -07001567static ssize_t
1568show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1569{
1570 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1571 struct nct6775_data *data = nct6775_update_device(dev);
1572 int nr = data->BEEP_BITS[sattr->index];
1573
1574 return sprintf(buf, "%u\n",
1575 (unsigned int)((data->beeps >> nr) & 0x01));
1576}
1577
1578static ssize_t
1579store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
1580 size_t count)
1581{
1582 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1583 struct nct6775_data *data = dev_get_drvdata(dev);
1584 int nr = data->BEEP_BITS[sattr->index];
1585 int regindex = nr >> 3;
1586 unsigned long val;
1587
1588 int err = kstrtoul(buf, 10, &val);
1589 if (err < 0)
1590 return err;
1591 if (val > 1)
1592 return -EINVAL;
1593
1594 mutex_lock(&data->update_lock);
1595 if (val)
1596 data->beeps |= (1ULL << nr);
1597 else
1598 data->beeps &= ~(1ULL << nr);
1599 nct6775_write_value(data, data->REG_BEEP[regindex],
1600 (data->beeps >> (regindex << 3)) & 0xff);
1601 mutex_unlock(&data->update_lock);
1602 return count;
1603}
1604
1605static ssize_t
1606show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1607{
1608 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1609 struct nct6775_data *data = nct6775_update_device(dev);
1610 unsigned int beep = 0;
1611 int nr;
1612
1613 /*
1614 * For temperatures, there is no fixed mapping from registers to beep
1615 * enable bits. Beep enable bits are determined by the temperature
1616 * source mapping.
1617 */
1618 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1619 if (nr >= 0) {
1620 int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1621 beep = (data->beeps >> bit) & 0x01;
1622 }
1623 return sprintf(buf, "%u\n", beep);
1624}
1625
1626static ssize_t
1627store_temp_beep(struct device *dev, struct device_attribute *attr,
1628 const char *buf, size_t count)
1629{
1630 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1631 struct nct6775_data *data = dev_get_drvdata(dev);
1632 int nr, bit, regindex;
1633 unsigned long val;
1634
1635 int err = kstrtoul(buf, 10, &val);
1636 if (err < 0)
1637 return err;
1638 if (val > 1)
1639 return -EINVAL;
1640
1641 nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1642 if (nr < 0)
Guenter Roecke8ab5082013-09-11 10:32:18 -07001643 return nr;
Guenter Roeck30846992013-06-24 22:21:59 -07001644
1645 bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1646 regindex = bit >> 3;
1647
1648 mutex_lock(&data->update_lock);
1649 if (val)
1650 data->beeps |= (1ULL << bit);
1651 else
1652 data->beeps &= ~(1ULL << bit);
1653 nct6775_write_value(data, data->REG_BEEP[regindex],
1654 (data->beeps >> (regindex << 3)) & 0xff);
1655 mutex_unlock(&data->update_lock);
1656
1657 return count;
1658}
1659
Guenter Roeckf73cf632013-03-18 09:22:50 -07001660static umode_t nct6775_in_is_visible(struct kobject *kobj,
1661 struct attribute *attr, int index)
1662{
1663 struct device *dev = container_of(kobj, struct device, kobj);
1664 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001665 int in = index / 5; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001666
Guenter Roeckf73cf632013-03-18 09:22:50 -07001667 if (!(data->have_in & (1 << in)))
1668 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001669
Guenter Roeckf73cf632013-03-18 09:22:50 -07001670 return attr->mode;
1671}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001672
Guenter Roeckf73cf632013-03-18 09:22:50 -07001673SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1674SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07001675SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
1676 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001677SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1678 store_in_reg, 0, 1);
1679SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1680 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001681
Guenter Roeckf73cf632013-03-18 09:22:50 -07001682/*
1683 * nct6775_in_is_visible uses the index into the following array
1684 * to determine if attributes should be created or not.
1685 * Any change in order or content must be matched.
1686 */
1687static struct sensor_device_template *nct6775_attributes_in_template[] = {
1688 &sensor_dev_template_in_input,
1689 &sensor_dev_template_in_alarm,
Guenter Roeck30846992013-06-24 22:21:59 -07001690 &sensor_dev_template_in_beep,
Guenter Roeckf73cf632013-03-18 09:22:50 -07001691 &sensor_dev_template_in_min,
1692 &sensor_dev_template_in_max,
1693 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001694};
1695
Guenter Roeckf73cf632013-03-18 09:22:50 -07001696static struct sensor_template_group nct6775_in_template_group = {
1697 .templates = nct6775_attributes_in_template,
1698 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001699};
1700
1701static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001702show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1703{
1704 struct nct6775_data *data = nct6775_update_device(dev);
1705 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1706 int nr = sattr->index;
1707 return sprintf(buf, "%d\n", data->rpm[nr]);
1708}
1709
1710static ssize_t
1711show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1712{
1713 struct nct6775_data *data = nct6775_update_device(dev);
1714 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1715 int nr = sattr->index;
1716 return sprintf(buf, "%d\n",
1717 data->fan_from_reg_min(data->fan_min[nr],
1718 data->fan_div[nr]));
1719}
1720
1721static ssize_t
1722show_fan_div(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, "%u\n", div_from_reg(data->fan_div[nr]));
1728}
1729
1730static ssize_t
1731store_fan_min(struct device *dev, struct device_attribute *attr,
1732 const char *buf, size_t count)
1733{
1734 struct nct6775_data *data = dev_get_drvdata(dev);
1735 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1736 int nr = sattr->index;
1737 unsigned long val;
1738 int err;
1739 unsigned int reg;
1740 u8 new_div;
1741
1742 err = kstrtoul(buf, 10, &val);
1743 if (err < 0)
1744 return err;
1745
1746 mutex_lock(&data->update_lock);
1747 if (!data->has_fan_div) {
1748 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1749 if (!val) {
1750 val = 0xff1f;
1751 } else {
1752 if (val > 1350000U)
1753 val = 135000U;
1754 val = 1350000U / val;
1755 val = (val & 0x1f) | ((val << 3) & 0xff00);
1756 }
1757 data->fan_min[nr] = val;
1758 goto write_min; /* Leave fan divider alone */
1759 }
1760 if (!val) {
1761 /* No min limit, alarm disabled */
1762 data->fan_min[nr] = 255;
1763 new_div = data->fan_div[nr]; /* No change */
1764 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1765 goto write_div;
1766 }
1767 reg = 1350000U / val;
1768 if (reg >= 128 * 255) {
1769 /*
1770 * Speed below this value cannot possibly be represented,
1771 * even with the highest divider (128)
1772 */
1773 data->fan_min[nr] = 254;
1774 new_div = 7; /* 128 == (1 << 7) */
1775 dev_warn(dev,
1776 "fan%u low limit %lu below minimum %u, set to minimum\n",
1777 nr + 1, val, data->fan_from_reg_min(254, 7));
1778 } else if (!reg) {
1779 /*
1780 * Speed above this value cannot possibly be represented,
1781 * even with the lowest divider (1)
1782 */
1783 data->fan_min[nr] = 1;
1784 new_div = 0; /* 1 == (1 << 0) */
1785 dev_warn(dev,
1786 "fan%u low limit %lu above maximum %u, set to maximum\n",
1787 nr + 1, val, data->fan_from_reg_min(1, 0));
1788 } else {
1789 /*
1790 * Automatically pick the best divider, i.e. the one such
1791 * that the min limit will correspond to a register value
1792 * in the 96..192 range
1793 */
1794 new_div = 0;
1795 while (reg > 192 && new_div < 7) {
1796 reg >>= 1;
1797 new_div++;
1798 }
1799 data->fan_min[nr] = reg;
1800 }
1801
1802write_div:
1803 /*
1804 * Write both the fan clock divider (if it changed) and the new
1805 * fan min (unconditionally)
1806 */
1807 if (new_div != data->fan_div[nr]) {
1808 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1809 nr + 1, div_from_reg(data->fan_div[nr]),
1810 div_from_reg(new_div));
1811 data->fan_div[nr] = new_div;
1812 nct6775_write_fan_div_common(data, nr);
1813 /* Give the chip time to sample a new speed value */
1814 data->last_updated = jiffies;
1815 }
1816
1817write_min:
1818 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1819 mutex_unlock(&data->update_lock);
1820
1821 return count;
1822}
1823
Guenter Roeck5c25d952012-12-11 07:29:06 -08001824static ssize_t
1825show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1826{
1827 struct nct6775_data *data = nct6775_update_device(dev);
1828 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1829 int p = data->fan_pulses[sattr->index];
1830
1831 return sprintf(buf, "%d\n", p ? : 4);
1832}
1833
1834static ssize_t
1835store_fan_pulses(struct device *dev, struct device_attribute *attr,
1836 const char *buf, size_t count)
1837{
1838 struct nct6775_data *data = dev_get_drvdata(dev);
1839 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1840 int nr = sattr->index;
1841 unsigned long val;
1842 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001843 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001844
1845 err = kstrtoul(buf, 10, &val);
1846 if (err < 0)
1847 return err;
1848
1849 if (val > 4)
1850 return -EINVAL;
1851
1852 mutex_lock(&data->update_lock);
1853 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001854 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1855 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1856 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1857 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001858 mutex_unlock(&data->update_lock);
1859
1860 return count;
1861}
1862
Guenter Roeckf73cf632013-03-18 09:22:50 -07001863static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1864 struct attribute *attr, int index)
1865{
1866 struct device *dev = container_of(kobj, struct device, kobj);
1867 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07001868 int fan = index / 6; /* fan index */
1869 int nr = index % 6; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001870
1871 if (!(data->has_fan & (1 << fan)))
1872 return 0;
1873
1874 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1875 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001876 if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001877 return 0;
Guenter Roeck30846992013-06-24 22:21:59 -07001878 if (nr == 4 && !(data->has_fan_min & (1 << fan)))
1879 return 0;
1880 if (nr == 5 && data->kind != nct6775)
Guenter Roeckf73cf632013-03-18 09:22:50 -07001881 return 0;
1882
1883 return attr->mode;
1884}
1885
1886SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1887SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1888 FAN_ALARM_BASE);
Guenter Roeck30846992013-06-24 22:21:59 -07001889SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
1890 store_beep, FAN_ALARM_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001891SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1892 store_fan_pulses, 0);
1893SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1894 store_fan_min, 0);
1895SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1896
1897/*
1898 * nct6775_fan_is_visible uses the index into the following array
1899 * to determine if attributes should be created or not.
1900 * Any change in order or content must be matched.
1901 */
1902static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1903 &sensor_dev_template_fan_input,
1904 &sensor_dev_template_fan_alarm, /* 1 */
Guenter Roeck30846992013-06-24 22:21:59 -07001905 &sensor_dev_template_fan_beep, /* 2 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001906 &sensor_dev_template_fan_pulses,
Guenter Roeck30846992013-06-24 22:21:59 -07001907 &sensor_dev_template_fan_min, /* 4 */
1908 &sensor_dev_template_fan_div, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001909 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001910};
1911
Guenter Roeckf73cf632013-03-18 09:22:50 -07001912static struct sensor_template_group nct6775_fan_template_group = {
1913 .templates = nct6775_attributes_fan_template,
1914 .is_visible = nct6775_fan_is_visible,
1915 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001916};
1917
1918static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001919show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1920{
1921 struct nct6775_data *data = nct6775_update_device(dev);
1922 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1923 int nr = sattr->index;
1924 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1925}
1926
1927static ssize_t
1928show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1929{
1930 struct nct6775_data *data = nct6775_update_device(dev);
1931 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1932 int nr = sattr->nr;
1933 int index = sattr->index;
1934
1935 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1936}
1937
1938static ssize_t
1939store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1940 size_t count)
1941{
1942 struct nct6775_data *data = dev_get_drvdata(dev);
1943 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1944 int nr = sattr->nr;
1945 int index = sattr->index;
1946 int err;
1947 long val;
1948
1949 err = kstrtol(buf, 10, &val);
1950 if (err < 0)
1951 return err;
1952
1953 mutex_lock(&data->update_lock);
1954 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1955 nct6775_write_temp(data, data->reg_temp[index][nr],
1956 data->temp[index][nr]);
1957 mutex_unlock(&data->update_lock);
1958 return count;
1959}
1960
1961static ssize_t
1962show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1963{
1964 struct nct6775_data *data = nct6775_update_device(dev);
1965 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1966
1967 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1968}
1969
1970static ssize_t
1971store_temp_offset(struct device *dev, struct device_attribute *attr,
1972 const char *buf, size_t count)
1973{
1974 struct nct6775_data *data = dev_get_drvdata(dev);
1975 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1976 int nr = sattr->index;
1977 long val;
1978 int err;
1979
1980 err = kstrtol(buf, 10, &val);
1981 if (err < 0)
1982 return err;
1983
1984 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1985
1986 mutex_lock(&data->update_lock);
1987 data->temp_offset[nr] = val;
1988 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1989 mutex_unlock(&data->update_lock);
1990
1991 return count;
1992}
1993
1994static ssize_t
1995show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1996{
1997 struct nct6775_data *data = nct6775_update_device(dev);
1998 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1999 int nr = sattr->index;
2000 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2001}
2002
2003static ssize_t
2004store_temp_type(struct device *dev, struct device_attribute *attr,
2005 const char *buf, size_t count)
2006{
2007 struct nct6775_data *data = nct6775_update_device(dev);
2008 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2009 int nr = sattr->index;
2010 unsigned long val;
2011 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07002012 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002013
2014 err = kstrtoul(buf, 10, &val);
2015 if (err < 0)
2016 return err;
2017
2018 if (val != 1 && val != 3 && val != 4)
2019 return -EINVAL;
2020
2021 mutex_lock(&data->update_lock);
2022
2023 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07002024 vbit = 0x02 << nr;
2025 dbit = data->DIODE_MASK << nr;
2026 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
2027 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002028 switch (val) {
2029 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07002030 vbat |= vbit;
2031 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002032 break;
2033 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07002034 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08002035 break;
2036 case 4: /* thermistor */
2037 break;
2038 }
2039 nct6775_write_value(data, data->REG_VBAT, vbat);
2040 nct6775_write_value(data, data->REG_DIODE, diode);
2041
2042 mutex_unlock(&data->update_lock);
2043 return count;
2044}
2045
Guenter Roeckf73cf632013-03-18 09:22:50 -07002046static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2047 struct attribute *attr, int index)
2048{
2049 struct device *dev = container_of(kobj, struct device, kobj);
2050 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck30846992013-06-24 22:21:59 -07002051 int temp = index / 10; /* temp index */
2052 int nr = index % 10; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002053
2054 if (!(data->have_temp & (1 << temp)))
2055 return 0;
2056
2057 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2058 return 0; /* alarm */
2059
Guenter Roeck30846992013-06-24 22:21:59 -07002060 if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2061 return 0; /* beep */
2062
2063 if (nr == 4 && !data->reg_temp[1][temp]) /* max */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002064 return 0;
2065
Guenter Roeck30846992013-06-24 22:21:59 -07002066 if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002067 return 0;
2068
Guenter Roeck30846992013-06-24 22:21:59 -07002069 if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002070 return 0;
2071
Guenter Roeck30846992013-06-24 22:21:59 -07002072 if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
Guenter Roeckb7a61352013-04-02 22:14:06 -07002073 return 0;
2074
2075 /* offset and type only apply to fixed sensors */
Guenter Roeck30846992013-06-24 22:21:59 -07002076 if (nr > 7 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07002077 return 0;
2078
2079 return attr->mode;
2080}
2081
2082SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
2083SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
2084SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
2085 store_temp, 0, 1);
2086SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
2087 show_temp, store_temp, 0, 2);
2088SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
2089 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07002090SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
2091 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002092SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
2093 show_temp_offset, store_temp_offset, 0);
2094SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
2095 store_temp_type, 0);
2096SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
Guenter Roeck30846992013-06-24 22:21:59 -07002097SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
2098 store_temp_beep, 0);
Guenter Roeckf73cf632013-03-18 09:22:50 -07002099
2100/*
2101 * nct6775_temp_is_visible uses the index into the following array
2102 * to determine if attributes should be created or not.
2103 * Any change in order or content must be matched.
2104 */
2105static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2106 &sensor_dev_template_temp_input,
2107 &sensor_dev_template_temp_label,
2108 &sensor_dev_template_temp_alarm, /* 2 */
Guenter Roeck30846992013-06-24 22:21:59 -07002109 &sensor_dev_template_temp_beep, /* 3 */
2110 &sensor_dev_template_temp_max, /* 4 */
2111 &sensor_dev_template_temp_max_hyst, /* 5 */
2112 &sensor_dev_template_temp_crit, /* 6 */
2113 &sensor_dev_template_temp_lcrit, /* 7 */
2114 &sensor_dev_template_temp_offset, /* 8 */
2115 &sensor_dev_template_temp_type, /* 9 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002116 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08002117};
2118
Guenter Roeckf73cf632013-03-18 09:22:50 -07002119static struct sensor_template_group nct6775_temp_template_group = {
2120 .templates = nct6775_attributes_temp_template,
2121 .is_visible = nct6775_temp_is_visible,
2122 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08002123};
2124
Guenter Roeckaa136e52012-12-04 03:26:05 -08002125static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002126show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2127{
2128 struct nct6775_data *data = nct6775_update_device(dev);
2129 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2130
2131 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
2132}
2133
2134static ssize_t
2135store_pwm_mode(struct device *dev, struct device_attribute *attr,
2136 const char *buf, size_t count)
2137{
2138 struct nct6775_data *data = dev_get_drvdata(dev);
2139 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2140 int nr = sattr->index;
2141 unsigned long val;
2142 int err;
2143 u8 reg;
2144
2145 err = kstrtoul(buf, 10, &val);
2146 if (err < 0)
2147 return err;
2148
2149 if (val > 1)
2150 return -EINVAL;
2151
2152 /* Setting DC mode is not supported for all chips/channels */
2153 if (data->REG_PWM_MODE[nr] == 0) {
2154 if (val)
2155 return -EINVAL;
2156 return count;
2157 }
2158
2159 mutex_lock(&data->update_lock);
2160 data->pwm_mode[nr] = val;
2161 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
2162 reg &= ~data->PWM_MODE_MASK[nr];
2163 if (val)
2164 reg |= data->PWM_MODE_MASK[nr];
2165 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2166 mutex_unlock(&data->update_lock);
2167 return count;
2168}
2169
2170static ssize_t
2171show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2172{
2173 struct nct6775_data *data = nct6775_update_device(dev);
2174 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2175 int nr = sattr->nr;
2176 int index = sattr->index;
2177 int pwm;
2178
2179 /*
2180 * For automatic fan control modes, show current pwm readings.
2181 * Otherwise, show the configured value.
2182 */
2183 if (index == 0 && data->pwm_enable[nr] > manual)
2184 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
2185 else
2186 pwm = data->pwm[index][nr];
2187
2188 return sprintf(buf, "%d\n", pwm);
2189}
2190
2191static ssize_t
2192store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2193 size_t count)
2194{
2195 struct nct6775_data *data = dev_get_drvdata(dev);
2196 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2197 int nr = sattr->nr;
2198 int index = sattr->index;
2199 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002200 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2201 int maxval[7]
2202 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002203 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002204 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002205
2206 err = kstrtoul(buf, 10, &val);
2207 if (err < 0)
2208 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002209 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002210
2211 mutex_lock(&data->update_lock);
2212 data->pwm[index][nr] = val;
2213 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002214 if (index == 2) { /* floor: disable if val == 0 */
2215 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2216 reg &= 0x7f;
2217 if (val)
2218 reg |= 0x80;
2219 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2220 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002221 mutex_unlock(&data->update_lock);
2222 return count;
2223}
2224
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002225/* Returns 0 if OK, -EINVAL otherwise */
2226static int check_trip_points(struct nct6775_data *data, int nr)
2227{
2228 int i;
2229
2230 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2231 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2232 return -EINVAL;
2233 }
2234 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2235 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2236 return -EINVAL;
2237 }
2238 /* validate critical temperature and pwm if enabled (pwm > 0) */
2239 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2240 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2241 data->auto_temp[nr][data->auto_pwm_num] ||
2242 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2243 data->auto_pwm[nr][data->auto_pwm_num])
2244 return -EINVAL;
2245 }
2246 return 0;
2247}
2248
2249static void pwm_update_registers(struct nct6775_data *data, int nr)
2250{
2251 u8 reg;
2252
2253 switch (data->pwm_enable[nr]) {
2254 case off:
2255 case manual:
2256 break;
2257 case speed_cruise:
2258 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2259 reg = (reg & ~data->tolerance_mask) |
2260 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2261 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2262 nct6775_write_value(data, data->REG_TARGET[nr],
2263 data->target_speed[nr] & 0xff);
2264 if (data->REG_TOLERANCE_H) {
2265 reg = (data->target_speed[nr] >> 8) & 0x0f;
2266 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2267 nct6775_write_value(data,
2268 data->REG_TOLERANCE_H[nr],
2269 reg);
2270 }
2271 break;
2272 case thermal_cruise:
2273 nct6775_write_value(data, data->REG_TARGET[nr],
2274 data->target_temp[nr]);
2275 /* intentional */
2276 default:
2277 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2278 reg = (reg & ~data->tolerance_mask) |
2279 data->temp_tolerance[0][nr];
2280 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2281 break;
2282 }
2283}
2284
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002285static ssize_t
2286show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2287{
2288 struct nct6775_data *data = nct6775_update_device(dev);
2289 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2290
2291 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2292}
2293
2294static ssize_t
2295store_pwm_enable(struct device *dev, struct device_attribute *attr,
2296 const char *buf, size_t count)
2297{
2298 struct nct6775_data *data = dev_get_drvdata(dev);
2299 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2300 int nr = sattr->index;
2301 unsigned long val;
2302 int err;
2303 u16 reg;
2304
2305 err = kstrtoul(buf, 10, &val);
2306 if (err < 0)
2307 return err;
2308
2309 if (val > sf4)
2310 return -EINVAL;
2311
2312 if (val == sf3 && data->kind != nct6775)
2313 return -EINVAL;
2314
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002315 if (val == sf4 && check_trip_points(data, nr)) {
2316 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2317 dev_err(dev, "Adjust trip points and try again\n");
2318 return -EINVAL;
2319 }
2320
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002321 mutex_lock(&data->update_lock);
2322 data->pwm_enable[nr] = val;
2323 if (val == off) {
2324 /*
2325 * turn off pwm control: select manual mode, set pwm to maximum
2326 */
2327 data->pwm[0][nr] = 255;
2328 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2329 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002330 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002331 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2332 reg &= 0x0f;
2333 reg |= pwm_enable_to_reg(val) << 4;
2334 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2335 mutex_unlock(&data->update_lock);
2336 return count;
2337}
2338
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002339static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002340show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002341{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002342 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002343
2344 for (i = 0; i < NUM_TEMP; i++) {
2345 if (!(data->have_temp & (1 << i)))
2346 continue;
2347 if (src == data->temp_src[i]) {
2348 sel = i + 1;
2349 break;
2350 }
2351 }
2352
2353 return sprintf(buf, "%d\n", sel);
2354}
2355
2356static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002357show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2358{
2359 struct nct6775_data *data = nct6775_update_device(dev);
2360 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2361 int index = sattr->index;
2362
2363 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2364}
2365
2366static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002367store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2368 const char *buf, size_t count)
2369{
2370 struct nct6775_data *data = nct6775_update_device(dev);
2371 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2372 int nr = sattr->index;
2373 unsigned long val;
2374 int err, reg, src;
2375
2376 err = kstrtoul(buf, 10, &val);
2377 if (err < 0)
2378 return err;
2379 if (val == 0 || val > NUM_TEMP)
2380 return -EINVAL;
2381 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2382 return -EINVAL;
2383
2384 mutex_lock(&data->update_lock);
2385 src = data->temp_src[val - 1];
2386 data->pwm_temp_sel[nr] = src;
2387 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2388 reg &= 0xe0;
2389 reg |= src;
2390 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2391 mutex_unlock(&data->update_lock);
2392
2393 return count;
2394}
2395
2396static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002397show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2398 char *buf)
2399{
2400 struct nct6775_data *data = nct6775_update_device(dev);
2401 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2402 int index = sattr->index;
2403
2404 return show_pwm_temp_sel_common(data, buf,
2405 data->pwm_weight_temp_sel[index]);
2406}
2407
2408static ssize_t
2409store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2410 const char *buf, size_t count)
2411{
2412 struct nct6775_data *data = nct6775_update_device(dev);
2413 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2414 int nr = sattr->index;
2415 unsigned long val;
2416 int err, reg, src;
2417
2418 err = kstrtoul(buf, 10, &val);
2419 if (err < 0)
2420 return err;
2421 if (val > NUM_TEMP)
2422 return -EINVAL;
2423 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2424 !data->temp_src[val - 1]))
2425 return -EINVAL;
2426
2427 mutex_lock(&data->update_lock);
2428 if (val) {
2429 src = data->temp_src[val - 1];
2430 data->pwm_weight_temp_sel[nr] = src;
2431 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2432 reg &= 0xe0;
2433 reg |= (src | 0x80);
2434 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2435 } else {
2436 data->pwm_weight_temp_sel[nr] = 0;
2437 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2438 reg &= 0x7f;
2439 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2440 }
2441 mutex_unlock(&data->update_lock);
2442
2443 return count;
2444}
2445
2446static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002447show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2448{
2449 struct nct6775_data *data = nct6775_update_device(dev);
2450 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2451
2452 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2453}
2454
2455static ssize_t
2456store_target_temp(struct device *dev, struct device_attribute *attr,
2457 const char *buf, size_t count)
2458{
2459 struct nct6775_data *data = dev_get_drvdata(dev);
2460 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2461 int nr = sattr->index;
2462 unsigned long val;
2463 int err;
2464
2465 err = kstrtoul(buf, 10, &val);
2466 if (err < 0)
2467 return err;
2468
2469 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2470 data->target_temp_mask);
2471
2472 mutex_lock(&data->update_lock);
2473 data->target_temp[nr] = val;
2474 pwm_update_registers(data, nr);
2475 mutex_unlock(&data->update_lock);
2476 return count;
2477}
2478
2479static ssize_t
2480show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2481{
2482 struct nct6775_data *data = nct6775_update_device(dev);
2483 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2484 int nr = sattr->index;
2485
2486 return sprintf(buf, "%d\n",
2487 fan_from_reg16(data->target_speed[nr],
2488 data->fan_div[nr]));
2489}
2490
2491static ssize_t
2492store_target_speed(struct device *dev, struct device_attribute *attr,
2493 const char *buf, size_t count)
2494{
2495 struct nct6775_data *data = dev_get_drvdata(dev);
2496 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2497 int nr = sattr->index;
2498 unsigned long val;
2499 int err;
2500 u16 speed;
2501
2502 err = kstrtoul(buf, 10, &val);
2503 if (err < 0)
2504 return err;
2505
2506 val = clamp_val(val, 0, 1350000U);
2507 speed = fan_to_reg(val, data->fan_div[nr]);
2508
2509 mutex_lock(&data->update_lock);
2510 data->target_speed[nr] = speed;
2511 pwm_update_registers(data, nr);
2512 mutex_unlock(&data->update_lock);
2513 return count;
2514}
2515
2516static ssize_t
2517show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2518 char *buf)
2519{
2520 struct nct6775_data *data = nct6775_update_device(dev);
2521 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2522 int nr = sattr->nr;
2523 int index = sattr->index;
2524
2525 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2526}
2527
2528static ssize_t
2529store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2530 const char *buf, size_t count)
2531{
2532 struct nct6775_data *data = dev_get_drvdata(dev);
2533 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2534 int nr = sattr->nr;
2535 int index = sattr->index;
2536 unsigned long val;
2537 int err;
2538
2539 err = kstrtoul(buf, 10, &val);
2540 if (err < 0)
2541 return err;
2542
2543 /* Limit tolerance as needed */
2544 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2545
2546 mutex_lock(&data->update_lock);
2547 data->temp_tolerance[index][nr] = val;
2548 if (index)
2549 pwm_update_registers(data, nr);
2550 else
2551 nct6775_write_value(data,
2552 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2553 val);
2554 mutex_unlock(&data->update_lock);
2555 return count;
2556}
2557
2558/*
2559 * Fan speed tolerance is a tricky beast, since the associated register is
2560 * a tick counter, but the value is reported and configured as rpm.
2561 * Compute resulting low and high rpm values and report the difference.
2562 */
2563static ssize_t
2564show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2565 char *buf)
2566{
2567 struct nct6775_data *data = nct6775_update_device(dev);
2568 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2569 int nr = sattr->index;
2570 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2571 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2572 int tolerance;
2573
2574 if (low <= 0)
2575 low = 1;
2576 if (high > 0xffff)
2577 high = 0xffff;
2578 if (high < low)
2579 high = low;
2580
2581 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2582 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2583
2584 return sprintf(buf, "%d\n", tolerance);
2585}
2586
2587static ssize_t
2588store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2589 const char *buf, size_t count)
2590{
2591 struct nct6775_data *data = dev_get_drvdata(dev);
2592 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2593 int nr = sattr->index;
2594 unsigned long val;
2595 int err;
2596 int low, high;
2597
2598 err = kstrtoul(buf, 10, &val);
2599 if (err < 0)
2600 return err;
2601
2602 high = fan_from_reg16(data->target_speed[nr],
2603 data->fan_div[nr]) + val;
2604 low = fan_from_reg16(data->target_speed[nr],
2605 data->fan_div[nr]) - val;
2606 if (low <= 0)
2607 low = 1;
2608 if (high < low)
2609 high = low;
2610
2611 val = (fan_to_reg(low, data->fan_div[nr]) -
2612 fan_to_reg(high, data->fan_div[nr])) / 2;
2613
2614 /* Limit tolerance as needed */
2615 val = clamp_val(val, 0, data->speed_tolerance_limit);
2616
2617 mutex_lock(&data->update_lock);
2618 data->target_speed_tolerance[nr] = val;
2619 pwm_update_registers(data, nr);
2620 mutex_unlock(&data->update_lock);
2621 return count;
2622}
2623
Guenter Roeckf73cf632013-03-18 09:22:50 -07002624SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2625SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2626 store_pwm_mode, 0);
2627SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2628 store_pwm_enable, 0);
2629SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2630 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2631SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2632 show_target_temp, store_target_temp, 0);
2633SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2634 show_target_speed, store_target_speed, 0);
2635SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2636 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002637
2638/* Smart Fan registers */
2639
2640static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002641show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2642{
2643 struct nct6775_data *data = nct6775_update_device(dev);
2644 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2645 int nr = sattr->nr;
2646 int index = sattr->index;
2647
2648 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2649}
2650
2651static ssize_t
2652store_weight_temp(struct device *dev, struct device_attribute *attr,
2653 const char *buf, size_t count)
2654{
2655 struct nct6775_data *data = dev_get_drvdata(dev);
2656 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2657 int nr = sattr->nr;
2658 int index = sattr->index;
2659 unsigned long val;
2660 int err;
2661
2662 err = kstrtoul(buf, 10, &val);
2663 if (err < 0)
2664 return err;
2665
2666 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2667
2668 mutex_lock(&data->update_lock);
2669 data->weight_temp[index][nr] = val;
2670 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2671 mutex_unlock(&data->update_lock);
2672 return count;
2673}
2674
Guenter Roeckf73cf632013-03-18 09:22:50 -07002675SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2676 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2677SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2678 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2679SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2680 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2681SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2682 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2683SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2684 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2685SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2686 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002687
2688static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002689show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2690{
2691 struct nct6775_data *data = nct6775_update_device(dev);
2692 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2693 int nr = sattr->nr;
2694 int index = sattr->index;
2695
2696 return sprintf(buf, "%d\n",
2697 step_time_from_reg(data->fan_time[index][nr],
2698 data->pwm_mode[nr]));
2699}
2700
2701static ssize_t
2702store_fan_time(struct device *dev, struct device_attribute *attr,
2703 const char *buf, size_t count)
2704{
2705 struct nct6775_data *data = dev_get_drvdata(dev);
2706 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2707 int nr = sattr->nr;
2708 int index = sattr->index;
2709 unsigned long val;
2710 int err;
2711
2712 err = kstrtoul(buf, 10, &val);
2713 if (err < 0)
2714 return err;
2715
2716 val = step_time_to_reg(val, data->pwm_mode[nr]);
2717 mutex_lock(&data->update_lock);
2718 data->fan_time[index][nr] = val;
2719 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2720 mutex_unlock(&data->update_lock);
2721 return count;
2722}
2723
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002724static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002725show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2726{
2727 struct nct6775_data *data = nct6775_update_device(dev);
2728 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2729
2730 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2731}
2732
2733static ssize_t
2734store_auto_pwm(struct device *dev, struct device_attribute *attr,
2735 const char *buf, size_t count)
2736{
2737 struct nct6775_data *data = dev_get_drvdata(dev);
2738 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2739 int nr = sattr->nr;
2740 int point = sattr->index;
2741 unsigned long val;
2742 int err;
2743 u8 reg;
2744
2745 err = kstrtoul(buf, 10, &val);
2746 if (err < 0)
2747 return err;
2748 if (val > 255)
2749 return -EINVAL;
2750
2751 if (point == data->auto_pwm_num) {
2752 if (data->kind != nct6775 && !val)
2753 return -EINVAL;
2754 if (data->kind != nct6779 && val)
2755 val = 0xff;
2756 }
2757
2758 mutex_lock(&data->update_lock);
2759 data->auto_pwm[nr][point] = val;
2760 if (point < data->auto_pwm_num) {
2761 nct6775_write_value(data,
2762 NCT6775_AUTO_PWM(data, nr, point),
2763 data->auto_pwm[nr][point]);
2764 } else {
2765 switch (data->kind) {
2766 case nct6775:
2767 /* disable if needed (pwm == 0) */
2768 reg = nct6775_read_value(data,
2769 NCT6775_REG_CRITICAL_ENAB[nr]);
2770 if (val)
2771 reg |= 0x02;
2772 else
2773 reg &= ~0x02;
2774 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2775 reg);
2776 break;
2777 case nct6776:
2778 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002779 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002780 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07002781 case nct6791:
Guenter Roeck6c009502012-07-01 08:23:15 -07002782 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002783 val);
2784 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002785 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002786 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002787 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002788 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002789 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002790 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002791 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002792 reg);
2793 break;
2794 }
2795 }
2796 mutex_unlock(&data->update_lock);
2797 return count;
2798}
2799
2800static ssize_t
2801show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2802{
2803 struct nct6775_data *data = nct6775_update_device(dev);
2804 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2805 int nr = sattr->nr;
2806 int point = sattr->index;
2807
2808 /*
2809 * We don't know for sure if the temperature is signed or unsigned.
2810 * Assume it is unsigned.
2811 */
2812 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2813}
2814
2815static ssize_t
2816store_auto_temp(struct device *dev, struct device_attribute *attr,
2817 const char *buf, size_t count)
2818{
2819 struct nct6775_data *data = dev_get_drvdata(dev);
2820 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2821 int nr = sattr->nr;
2822 int point = sattr->index;
2823 unsigned long val;
2824 int err;
2825
2826 err = kstrtoul(buf, 10, &val);
2827 if (err)
2828 return err;
2829 if (val > 255000)
2830 return -EINVAL;
2831
2832 mutex_lock(&data->update_lock);
2833 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2834 if (point < data->auto_pwm_num) {
2835 nct6775_write_value(data,
2836 NCT6775_AUTO_TEMP(data, nr, point),
2837 data->auto_temp[nr][point]);
2838 } else {
2839 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2840 data->auto_temp[nr][point]);
2841 }
2842 mutex_unlock(&data->update_lock);
2843 return count;
2844}
2845
Guenter Roeckf73cf632013-03-18 09:22:50 -07002846static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2847 struct attribute *attr, int index)
2848{
2849 struct device *dev = container_of(kobj, struct device, kobj);
2850 struct nct6775_data *data = dev_get_drvdata(dev);
2851 int pwm = index / 36; /* pwm index */
2852 int nr = index % 36; /* attribute index */
2853
2854 if (!(data->has_pwm & (1 << pwm)))
2855 return 0;
2856
2857 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2858 return 0;
2859 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2860 return 0;
2861 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2862 return 0;
2863
2864 if (nr >= 22 && nr <= 35) { /* auto point */
2865 int api = (nr - 22) / 2; /* auto point index */
2866
2867 if (api > data->auto_pwm_num)
2868 return 0;
2869 }
2870 return attr->mode;
2871}
2872
2873SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2874 show_fan_time, store_fan_time, 0, 0);
2875SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2876 show_fan_time, store_fan_time, 0, 1);
2877SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2878 show_fan_time, store_fan_time, 0, 2);
2879SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2880 store_pwm, 0, 1);
2881SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2882 store_pwm, 0, 2);
2883SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2884 show_temp_tolerance, store_temp_tolerance, 0, 0);
2885SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2886 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2887 0, 1);
2888
2889SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2890 0, 3);
2891
2892SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2893 store_pwm, 0, 4);
2894
2895SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2896 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2897SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2898 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2899
2900SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2901 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2902SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2903 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2904
2905SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2906 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2907SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2908 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2909
2910SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2911 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2912SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2913 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2914
2915SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2916 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2917SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2918 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2919
2920SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2921 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2922SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2923 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2924
2925SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2926 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2927SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2928 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2929
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002930/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002931 * nct6775_pwm_is_visible uses the index into the following array
2932 * to determine if attributes should be created or not.
2933 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002934 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002935static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2936 &sensor_dev_template_pwm,
2937 &sensor_dev_template_pwm_mode,
2938 &sensor_dev_template_pwm_enable,
2939 &sensor_dev_template_pwm_temp_sel,
2940 &sensor_dev_template_pwm_temp_tolerance,
2941 &sensor_dev_template_pwm_crit_temp_tolerance,
2942 &sensor_dev_template_pwm_target_temp,
2943 &sensor_dev_template_fan_target,
2944 &sensor_dev_template_fan_tolerance,
2945 &sensor_dev_template_pwm_stop_time,
2946 &sensor_dev_template_pwm_step_up_time,
2947 &sensor_dev_template_pwm_step_down_time,
2948 &sensor_dev_template_pwm_start,
2949 &sensor_dev_template_pwm_floor,
2950 &sensor_dev_template_pwm_weight_temp_sel,
2951 &sensor_dev_template_pwm_weight_temp_step,
2952 &sensor_dev_template_pwm_weight_temp_step_tol,
2953 &sensor_dev_template_pwm_weight_temp_step_base,
2954 &sensor_dev_template_pwm_weight_duty_step,
2955 &sensor_dev_template_pwm_max, /* 19 */
2956 &sensor_dev_template_pwm_step, /* 20 */
2957 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2958 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2959 &sensor_dev_template_pwm_auto_point1_temp,
2960 &sensor_dev_template_pwm_auto_point2_pwm,
2961 &sensor_dev_template_pwm_auto_point2_temp,
2962 &sensor_dev_template_pwm_auto_point3_pwm,
2963 &sensor_dev_template_pwm_auto_point3_temp,
2964 &sensor_dev_template_pwm_auto_point4_pwm,
2965 &sensor_dev_template_pwm_auto_point4_temp,
2966 &sensor_dev_template_pwm_auto_point5_pwm,
2967 &sensor_dev_template_pwm_auto_point5_temp,
2968 &sensor_dev_template_pwm_auto_point6_pwm,
2969 &sensor_dev_template_pwm_auto_point6_temp,
2970 &sensor_dev_template_pwm_auto_point7_pwm,
2971 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002972
Guenter Roeckf73cf632013-03-18 09:22:50 -07002973 NULL
2974};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002975
Guenter Roeckf73cf632013-03-18 09:22:50 -07002976static struct sensor_template_group nct6775_pwm_template_group = {
2977 .templates = nct6775_attributes_pwm_template,
2978 .is_visible = nct6775_pwm_is_visible,
2979 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002980};
2981
2982static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002983show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2984{
2985 struct nct6775_data *data = dev_get_drvdata(dev);
2986 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
2987}
2988
2989static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2990
Guenter Roecka6bd5872012-12-04 03:13:34 -08002991/* Case open detection */
2992
2993static ssize_t
2994clear_caseopen(struct device *dev, struct device_attribute *attr,
2995 const char *buf, size_t count)
2996{
2997 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roecka6bd5872012-12-04 03:13:34 -08002998 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
2999 unsigned long val;
3000 u8 reg;
3001 int ret;
3002
3003 if (kstrtoul(buf, 10, &val) || val != 0)
3004 return -EINVAL;
3005
3006 mutex_lock(&data->update_lock);
3007
3008 /*
3009 * Use CR registers to clear caseopen status.
3010 * The CR registers are the same for all chips, and not all chips
3011 * support clearing the caseopen status through "regular" registers.
3012 */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003013 ret = superio_enter(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003014 if (ret) {
3015 count = ret;
3016 goto error;
3017 }
3018
Guenter Roeckdf612d52013-07-08 13:15:04 -07003019 superio_select(data->sioreg, NCT6775_LD_ACPI);
3020 reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003021 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003022 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003023 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
Guenter Roeckdf612d52013-07-08 13:15:04 -07003024 superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
3025 superio_exit(data->sioreg);
Guenter Roecka6bd5872012-12-04 03:13:34 -08003026
3027 data->valid = false; /* Force cache refresh */
3028error:
3029 mutex_unlock(&data->update_lock);
3030 return count;
3031}
3032
Guenter Roeckf73cf632013-03-18 09:22:50 -07003033static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
3034 clear_caseopen, INTRUSION_ALARM_BASE);
3035static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
3036 clear_caseopen, INTRUSION_ALARM_BASE + 1);
Guenter Roeck30846992013-06-24 22:21:59 -07003037static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
3038 store_beep, INTRUSION_ALARM_BASE);
3039static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
3040 store_beep, INTRUSION_ALARM_BASE + 1);
3041static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
3042 store_beep, BEEP_ENABLE_BASE);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003043
3044static umode_t nct6775_other_is_visible(struct kobject *kobj,
3045 struct attribute *attr, int index)
3046{
3047 struct device *dev = container_of(kobj, struct device, kobj);
3048 struct nct6775_data *data = dev_get_drvdata(dev);
3049
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003050 if (index == 0 && !data->have_vid)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003051 return 0;
3052
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003053 if (index == 1 || index == 2) {
3054 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
Guenter Roeckf73cf632013-03-18 09:22:50 -07003055 return 0;
3056 }
3057
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003058 if (index == 3 || index == 4) {
3059 if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
Guenter Roeck30846992013-06-24 22:21:59 -07003060 return 0;
3061 }
3062
Guenter Roeckf73cf632013-03-18 09:22:50 -07003063 return attr->mode;
3064}
3065
3066/*
3067 * nct6775_other_is_visible uses the index into the following array
3068 * to determine if attributes should be created or not.
3069 * Any change in order or content must be matched.
3070 */
3071static struct attribute *nct6775_attributes_other[] = {
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003072 &dev_attr_cpu0_vid.attr, /* 0 */
3073 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
3074 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
3075 &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
3076 &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
3077 &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003078
3079 NULL
3080};
3081
3082static const struct attribute_group nct6775_group_other = {
3083 .attrs = nct6775_attributes_other,
3084 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08003085};
3086
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003087static inline void nct6775_init_device(struct nct6775_data *data)
3088{
Guenter Roeckaa136e52012-12-04 03:26:05 -08003089 int i;
3090 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003091
3092 /* Start monitoring if needed */
3093 if (data->REG_CONFIG) {
3094 tmp = nct6775_read_value(data, data->REG_CONFIG);
3095 if (!(tmp & 0x01))
3096 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3097 }
3098
Guenter Roeckaa136e52012-12-04 03:26:05 -08003099 /* Enable temperature sensors if needed */
3100 for (i = 0; i < NUM_TEMP; i++) {
3101 if (!(data->have_temp & (1 << i)))
3102 continue;
3103 if (!data->reg_temp_config[i])
3104 continue;
3105 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
3106 if (tmp & 0x01)
3107 nct6775_write_value(data, data->reg_temp_config[i],
3108 tmp & 0xfe);
3109 }
3110
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003111 /* Enable VBAT monitoring if needed */
3112 tmp = nct6775_read_value(data, data->REG_VBAT);
3113 if (!(tmp & 0x01))
3114 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003115
3116 diode = nct6775_read_value(data, data->REG_DIODE);
3117
3118 for (i = 0; i < data->temp_fixed_num; i++) {
3119 if (!(data->have_temp_fixed & (1 << i)))
3120 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07003121 if ((tmp & (data->DIODE_MASK << i))) /* diode */
3122 data->temp_type[i]
3123 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08003124 else /* thermistor */
3125 data->temp_type[i] = 4;
3126 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003127}
3128
Guenter Roeckf73cf632013-03-18 09:22:50 -07003129static void
Guenter Roeckdf612d52013-07-08 13:15:04 -07003130nct6775_check_fan_inputs(struct nct6775_data *data)
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003131{
David Bartley578ab5f2013-06-24 22:28:28 -07003132 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3133 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003134 int sioreg = data->sioreg;
3135 int regval;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003136
3137 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3138 if (data->kind == nct6775) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003139 regval = superio_inb(sioreg, 0x2c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003140
3141 fan3pin = regval & (1 << 6);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003142 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003143
3144 /* On NCT6775, fan4 shares pins with the fdc interface */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003145 fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
David Bartley578ab5f2013-06-24 22:28:28 -07003146 fan4min = false;
3147 fan5pin = false;
3148 fan6pin = false;
3149 pwm4pin = false;
3150 pwm5pin = false;
3151 pwm6pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003152 } else if (data->kind == nct6776) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003153 bool gpok = superio_inb(sioreg, 0x27) & 0x80;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003154
Guenter Roeckdf612d52013-07-08 13:15:04 -07003155 superio_select(sioreg, NCT6775_LD_HWM);
3156 regval = superio_inb(sioreg, SIO_REG_ENABLE);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003157
3158 if (regval & 0x80)
3159 fan3pin = gpok;
3160 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003161 fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003162
3163 if (regval & 0x40)
3164 fan4pin = gpok;
3165 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003166 fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003167
3168 if (regval & 0x20)
3169 fan5pin = gpok;
3170 else
Guenter Roeckdf612d52013-07-08 13:15:04 -07003171 fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003172
3173 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003174 fan6pin = false;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003175 pwm3pin = fan3pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003176 pwm4pin = false;
3177 pwm5pin = false;
3178 pwm6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003179 } else if (data->kind == nct6106) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003180 regval = superio_inb(sioreg, 0x24);
Guenter Roeck6c009502012-07-01 08:23:15 -07003181 fan3pin = !(regval & 0x80);
3182 pwm3pin = regval & 0x08;
Guenter Roeck6c009502012-07-01 08:23:15 -07003183
3184 fan4pin = false;
3185 fan4min = false;
3186 fan5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003187 fan6pin = false;
Guenter Roeck6c009502012-07-01 08:23:15 -07003188 pwm4pin = false;
3189 pwm5pin = false;
David Bartley578ab5f2013-06-24 22:28:28 -07003190 pwm6pin = false;
3191 } else { /* NCT6779D or NCT6791D */
Guenter Roeckdf612d52013-07-08 13:15:04 -07003192 regval = superio_inb(sioreg, 0x1c);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003193
3194 fan3pin = !(regval & (1 << 5));
3195 fan4pin = !(regval & (1 << 6));
3196 fan5pin = !(regval & (1 << 7));
3197
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003198 pwm3pin = !(regval & (1 << 0));
3199 pwm4pin = !(regval & (1 << 1));
3200 pwm5pin = !(regval & (1 << 2));
3201
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003202 fan4min = fan4pin;
David Bartley578ab5f2013-06-24 22:28:28 -07003203
3204 if (data->kind == nct6791) {
Guenter Roeckdf612d52013-07-08 13:15:04 -07003205 regval = superio_inb(sioreg, 0x2d);
David Bartley578ab5f2013-06-24 22:28:28 -07003206 fan6pin = (regval & (1 << 1));
3207 pwm6pin = (regval & (1 << 0));
3208 } else { /* NCT6779D */
3209 fan6pin = false;
3210 pwm6pin = false;
3211 }
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003212 }
3213
David Bartley578ab5f2013-06-24 22:28:28 -07003214 /* fan 1 and 2 (0x03) are always present */
3215 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3216 (fan5pin << 4) | (fan6pin << 5);
3217 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3218 (fan5pin << 4);
3219 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3220 (pwm5pin << 4) | (pwm6pin << 5);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003221}
3222
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003223static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3224 int *available, int *mask)
3225{
3226 int i;
3227 u8 src;
3228
3229 for (i = 0; i < data->pwm_num && *available; i++) {
3230 int index;
3231
3232 if (!regp[i])
3233 continue;
3234 src = nct6775_read_value(data, regp[i]);
3235 src &= 0x1f;
3236 if (!src || (*mask & (1 << src)))
3237 continue;
3238 if (src >= data->temp_label_num ||
3239 !strlen(data->temp_label[src]))
3240 continue;
3241
3242 index = __ffs(*available);
3243 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3244 *available &= ~(1 << index);
3245 *mask |= 1 << src;
3246 }
3247}
3248
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003249static int nct6775_probe(struct platform_device *pdev)
3250{
3251 struct device *dev = &pdev->dev;
Jingoo Hana8b3a3a2013-07-30 17:13:06 +09003252 struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003253 struct nct6775_data *data;
3254 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003255 int i, s, err = 0;
3256 int src, mask, available;
3257 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3258 const u16 *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003259 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003260 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003261 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003262 struct attribute_group *group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003263
3264 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3265 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3266 DRVNAME))
3267 return -EBUSY;
3268
3269 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3270 GFP_KERNEL);
3271 if (!data)
3272 return -ENOMEM;
3273
3274 data->kind = sio_data->kind;
Guenter Roeckdf612d52013-07-08 13:15:04 -07003275 data->sioreg = sio_data->sioreg;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003276 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003277 mutex_init(&data->update_lock);
3278 data->name = nct6775_device_names[data->kind];
3279 data->bank = 0xff; /* Force initial bank selection */
3280 platform_set_drvdata(pdev, data);
3281
3282 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003283 case nct6106:
3284 data->in_num = 9;
3285 data->pwm_num = 3;
3286 data->auto_pwm_num = 4;
3287 data->temp_fixed_num = 3;
3288 data->num_temp_alarms = 6;
Guenter Roeck30846992013-06-24 22:21:59 -07003289 data->num_temp_beeps = 6;
Guenter Roeck6c009502012-07-01 08:23:15 -07003290
3291 data->fan_from_reg = fan_from_reg13;
3292 data->fan_from_reg_min = fan_from_reg13;
3293
3294 data->temp_label = nct6776_temp_label;
3295 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3296
3297 data->REG_VBAT = NCT6106_REG_VBAT;
3298 data->REG_DIODE = NCT6106_REG_DIODE;
3299 data->DIODE_MASK = NCT6106_DIODE_MASK;
3300 data->REG_VIN = NCT6106_REG_IN;
3301 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3302 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3303 data->REG_TARGET = NCT6106_REG_TARGET;
3304 data->REG_FAN = NCT6106_REG_FAN;
3305 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3306 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3307 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3308 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3309 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3310 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3311 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3312 data->REG_PWM[0] = NCT6106_REG_PWM;
3313 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3314 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3315 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3316 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3317 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3318 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3319 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3320 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3321 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3322 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3323 data->REG_CRITICAL_TEMP_TOLERANCE
3324 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3325 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3326 data->CRITICAL_PWM_ENABLE_MASK
3327 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3328 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3329 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3330 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3331 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3332 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3333 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3334 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3335 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3336 data->REG_ALARM = NCT6106_REG_ALARM;
3337 data->ALARM_BITS = NCT6106_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003338 data->REG_BEEP = NCT6106_REG_BEEP;
3339 data->BEEP_BITS = NCT6106_BEEP_BITS;
Guenter Roeck6c009502012-07-01 08:23:15 -07003340
3341 reg_temp = NCT6106_REG_TEMP;
3342 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3343 reg_temp_over = NCT6106_REG_TEMP_OVER;
3344 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3345 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3346 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3347 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003348 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3349 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003350
3351 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003352 case nct6775:
3353 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003354 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003355 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003356 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003357 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003358 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003359 data->num_temp_beeps = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003360
3361 data->ALARM_BITS = NCT6775_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003362 data->BEEP_BITS = NCT6775_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003363
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003364 data->fan_from_reg = fan_from_reg16;
3365 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003366 data->target_temp_mask = 0x7f;
3367 data->tolerance_mask = 0x0f;
3368 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003369
Guenter Roeckaa136e52012-12-04 03:26:05 -08003370 data->temp_label = nct6775_temp_label;
3371 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3372
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003373 data->REG_CONFIG = NCT6775_REG_CONFIG;
3374 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003375 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003376 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003377 data->REG_VIN = NCT6775_REG_IN;
3378 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3379 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003380 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003381 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003382 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003383 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003384 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003385 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003386 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3387 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3388 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003389 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003390 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3391 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3392 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3393 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003394 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003395 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3396 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3397 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003398 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3399 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3400 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3401 data->REG_CRITICAL_TEMP_TOLERANCE
3402 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003403 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3404 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003405 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003406 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3407 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3408 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3409 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003410 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003411 data->REG_BEEP = NCT6775_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003412
3413 reg_temp = NCT6775_REG_TEMP;
3414 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3415 reg_temp_over = NCT6775_REG_TEMP_OVER;
3416 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3417 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3418 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3419 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3420
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003421 break;
3422 case nct6776:
3423 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003424 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003425 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003426 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003427 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003428 data->num_temp_alarms = 3;
Guenter Roeck30846992013-06-24 22:21:59 -07003429 data->num_temp_beeps = 6;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003430
3431 data->ALARM_BITS = NCT6776_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003432 data->BEEP_BITS = NCT6776_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003433
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003434 data->fan_from_reg = fan_from_reg13;
3435 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003436 data->target_temp_mask = 0xff;
3437 data->tolerance_mask = 0x07;
3438 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003439
Guenter Roeckaa136e52012-12-04 03:26:05 -08003440 data->temp_label = nct6776_temp_label;
3441 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3442
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003443 data->REG_CONFIG = NCT6775_REG_CONFIG;
3444 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003445 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003446 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003447 data->REG_VIN = NCT6775_REG_IN;
3448 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3449 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003450 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003451 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003452 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003453 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003454 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003455 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003456 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3457 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3458 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3459 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003460 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003461 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3462 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003463 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3464 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003465 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3466 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3467 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003468 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3469 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3470 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3471 data->REG_CRITICAL_TEMP_TOLERANCE
3472 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003473 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3474 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003475 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003476 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3477 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3478 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3479 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003480 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003481 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003482
3483 reg_temp = NCT6775_REG_TEMP;
3484 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3485 reg_temp_over = NCT6775_REG_TEMP_OVER;
3486 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3487 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3488 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3489 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3490
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003491 break;
3492 case nct6779:
3493 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003494 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003495 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003496 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003497 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003498 data->num_temp_alarms = 2;
Guenter Roeck30846992013-06-24 22:21:59 -07003499 data->num_temp_beeps = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003500
3501 data->ALARM_BITS = NCT6779_ALARM_BITS;
Guenter Roeck30846992013-06-24 22:21:59 -07003502 data->BEEP_BITS = NCT6779_BEEP_BITS;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003503
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003504 data->fan_from_reg = fan_from_reg13;
3505 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003506 data->target_temp_mask = 0xff;
3507 data->tolerance_mask = 0x07;
3508 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003509
Guenter Roeckaa136e52012-12-04 03:26:05 -08003510 data->temp_label = nct6779_temp_label;
3511 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3512
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003513 data->REG_CONFIG = NCT6775_REG_CONFIG;
3514 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003515 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003516 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003517 data->REG_VIN = NCT6779_REG_IN;
3518 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3519 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003520 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003521 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003522 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003523 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003524 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003525 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003526 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3527 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3528 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3529 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003530 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003531 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3532 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003533 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3534 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003535 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3536 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3537 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003538 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3539 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3540 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3541 data->REG_CRITICAL_TEMP_TOLERANCE
3542 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003543 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3544 data->CRITICAL_PWM_ENABLE_MASK
3545 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3546 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003547 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3548 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003549 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003550 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3551 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3552 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3553 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003554 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeck30846992013-06-24 22:21:59 -07003555 data->REG_BEEP = NCT6776_REG_BEEP;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003556
3557 reg_temp = NCT6779_REG_TEMP;
3558 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3559 reg_temp_over = NCT6779_REG_TEMP_OVER;
3560 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3561 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3562 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3563 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3564
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003565 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003566 case nct6791:
3567 data->in_num = 15;
3568 data->pwm_num = 6;
3569 data->auto_pwm_num = 4;
3570 data->has_fan_div = false;
3571 data->temp_fixed_num = 6;
3572 data->num_temp_alarms = 2;
3573 data->num_temp_beeps = 2;
3574
3575 data->ALARM_BITS = NCT6791_ALARM_BITS;
3576 data->BEEP_BITS = NCT6779_BEEP_BITS;
3577
3578 data->fan_from_reg = fan_from_reg13;
3579 data->fan_from_reg_min = fan_from_reg13;
3580 data->target_temp_mask = 0xff;
3581 data->tolerance_mask = 0x07;
3582 data->speed_tolerance_limit = 63;
3583
3584 data->temp_label = nct6779_temp_label;
3585 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3586
3587 data->REG_CONFIG = NCT6775_REG_CONFIG;
3588 data->REG_VBAT = NCT6775_REG_VBAT;
3589 data->REG_DIODE = NCT6775_REG_DIODE;
3590 data->DIODE_MASK = NCT6775_DIODE_MASK;
3591 data->REG_VIN = NCT6779_REG_IN;
3592 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3593 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3594 data->REG_TARGET = NCT6775_REG_TARGET;
3595 data->REG_FAN = NCT6779_REG_FAN;
3596 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3597 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3598 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3599 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3600 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3601 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3602 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3603 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3604 data->REG_PWM[0] = NCT6775_REG_PWM;
3605 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3606 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3607 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3608 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3609 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3610 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3611 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3612 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3613 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3614 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3615 data->REG_CRITICAL_TEMP_TOLERANCE
3616 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3617 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3618 data->CRITICAL_PWM_ENABLE_MASK
3619 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3620 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3621 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3622 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3623 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3624 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3625 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3626 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3627 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3628 data->REG_ALARM = NCT6791_REG_ALARM;
3629 data->REG_BEEP = NCT6776_REG_BEEP;
3630
3631 reg_temp = NCT6779_REG_TEMP;
3632 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3633 reg_temp_over = NCT6779_REG_TEMP_OVER;
3634 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3635 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3636 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3637 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3638
3639 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003640 default:
3641 return -ENODEV;
3642 }
3643 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003644 data->have_temp = 0;
3645
3646 /*
3647 * On some boards, not all available temperature sources are monitored,
3648 * even though some of the monitoring registers are unused.
3649 * Get list of unused monitoring registers, then detect if any fan
3650 * controls are configured to use unmonitored temperature sources.
3651 * If so, assign the unmonitored temperature sources to available
3652 * monitoring registers.
3653 */
3654 mask = 0;
3655 available = 0;
3656 for (i = 0; i < num_reg_temp; i++) {
3657 if (reg_temp[i] == 0)
3658 continue;
3659
3660 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3661 if (!src || (mask & (1 << src)))
3662 available |= 1 << i;
3663
3664 mask |= 1 << src;
3665 }
3666
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003667 /*
3668 * Now find unmonitored temperature registers and enable monitoring
3669 * if additional monitoring registers are available.
3670 */
3671 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3672 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3673
Guenter Roeckaa136e52012-12-04 03:26:05 -08003674 mask = 0;
3675 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3676 for (i = 0; i < num_reg_temp; i++) {
3677 if (reg_temp[i] == 0)
3678 continue;
3679
3680 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3681 if (!src || (mask & (1 << src)))
3682 continue;
3683
3684 if (src >= data->temp_label_num ||
3685 !strlen(data->temp_label[src])) {
3686 dev_info(dev,
3687 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3688 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3689 continue;
3690 }
3691
3692 mask |= 1 << src;
3693
3694 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3695 if (src <= data->temp_fixed_num) {
3696 data->have_temp |= 1 << (src - 1);
3697 data->have_temp_fixed |= 1 << (src - 1);
3698 data->reg_temp[0][src - 1] = reg_temp[i];
3699 data->reg_temp[1][src - 1] = reg_temp_over[i];
3700 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003701 if (reg_temp_crit_h && reg_temp_crit_h[i])
3702 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3703 else if (reg_temp_crit[src - 1])
3704 data->reg_temp[3][src - 1]
3705 = reg_temp_crit[src - 1];
3706 if (reg_temp_crit_l && reg_temp_crit_l[i])
3707 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003708 data->reg_temp_config[src - 1] = reg_temp_config[i];
3709 data->temp_src[src - 1] = src;
3710 continue;
3711 }
3712
3713 if (s >= NUM_TEMP)
3714 continue;
3715
3716 /* Use dynamic index for other sources */
3717 data->have_temp |= 1 << s;
3718 data->reg_temp[0][s] = reg_temp[i];
3719 data->reg_temp[1][s] = reg_temp_over[i];
3720 data->reg_temp[2][s] = reg_temp_hyst[i];
3721 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003722 if (reg_temp_crit_h && reg_temp_crit_h[i])
3723 data->reg_temp[3][s] = reg_temp_crit_h[i];
3724 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003725 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003726 if (reg_temp_crit_l && reg_temp_crit_l[i])
3727 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003728
3729 data->temp_src[s] = src;
3730 s++;
3731 }
3732
3733#ifdef USE_ALTERNATE
3734 /*
3735 * Go through the list of alternate temp registers and enable
3736 * if possible.
3737 * The temperature is already monitored if the respective bit in <mask>
3738 * is set.
3739 */
3740 for (i = 0; i < data->temp_label_num - 1; i++) {
3741 if (!reg_temp_alternate[i])
3742 continue;
3743 if (mask & (1 << (i + 1)))
3744 continue;
3745 if (i < data->temp_fixed_num) {
3746 if (data->have_temp & (1 << i))
3747 continue;
3748 data->have_temp |= 1 << i;
3749 data->have_temp_fixed |= 1 << i;
3750 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003751 if (i < num_reg_temp) {
3752 data->reg_temp[1][i] = reg_temp_over[i];
3753 data->reg_temp[2][i] = reg_temp_hyst[i];
3754 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003755 data->temp_src[i] = i + 1;
3756 continue;
3757 }
3758
3759 if (s >= NUM_TEMP) /* Abort if no more space */
3760 break;
3761
3762 data->have_temp |= 1 << s;
3763 data->reg_temp[0][s] = reg_temp_alternate[i];
3764 data->temp_src[s] = i + 1;
3765 s++;
3766 }
3767#endif /* USE_ALTERNATE */
3768
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003769 /* Initialize the chip */
3770 nct6775_init_device(data);
3771
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003772 err = superio_enter(sio_data->sioreg);
3773 if (err)
3774 return err;
3775
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003776 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3777 switch (data->kind) {
3778 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003779 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003780 break;
3781 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003782 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003783 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003784 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003785 case nct6779:
David Bartley578ab5f2013-06-24 22:28:28 -07003786 case nct6791:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003787 break;
3788 }
3789
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003790 /*
3791 * Read VID value
3792 * We can get the VID input values directly at logical device D 0xe3.
3793 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003794 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003795 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3796 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3797 data->vrm = vid_which_vrm();
3798 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003799
3800 if (fan_debounce) {
3801 u8 tmp;
3802
3803 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3804 tmp = superio_inb(sio_data->sioreg,
3805 NCT6775_REG_CR_FAN_DEBOUNCE);
3806 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003807 case nct6106:
3808 tmp |= 0xe0;
3809 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003810 case nct6775:
3811 tmp |= 0x1e;
3812 break;
3813 case nct6776:
3814 case nct6779:
3815 tmp |= 0x3e;
3816 break;
David Bartley578ab5f2013-06-24 22:28:28 -07003817 case nct6791:
3818 tmp |= 0x7e;
3819 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003820 }
3821 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3822 tmp);
3823 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3824 data->name);
3825 }
3826
Guenter Roeckdf612d52013-07-08 13:15:04 -07003827 nct6775_check_fan_inputs(data);
Guenter Roeckf73cf632013-03-18 09:22:50 -07003828
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003829 superio_exit(sio_data->sioreg);
3830
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003831 /* Read fan clock dividers immediately */
3832 nct6775_init_fan_common(dev, data);
3833
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003834 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003835 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3836 data->pwm_num);
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003837 if (IS_ERR(group))
3838 return PTR_ERR(group);
3839
3840 data->groups[data->num_attr_groups++] = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003841
Guenter Roeckf73cf632013-03-18 09:22:50 -07003842 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3843 fls(data->have_in));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003844 if (IS_ERR(group))
3845 return PTR_ERR(group);
3846
3847 data->groups[data->num_attr_groups++] = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003848
Guenter Roeckf73cf632013-03-18 09:22:50 -07003849 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3850 fls(data->has_fan));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003851 if (IS_ERR(group))
3852 return PTR_ERR(group);
3853
3854 data->groups[data->num_attr_groups++] = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003855
Guenter Roeckf73cf632013-03-18 09:22:50 -07003856 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3857 fls(data->have_temp));
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003858 if (IS_ERR(group))
3859 return PTR_ERR(group);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003860
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003861 data->groups[data->num_attr_groups++] = group;
3862 data->groups[data->num_attr_groups++] = &nct6775_group_other;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003863
Guenter Roeck615fc8c2013-07-06 09:43:30 -07003864 data->hwmon_dev = hwmon_device_register_with_groups(dev, data->name,
3865 data, data->groups);
3866 if (IS_ERR(data->hwmon_dev))
3867 return PTR_ERR(data->hwmon_dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003868
3869 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003870}
3871
3872static int nct6775_remove(struct platform_device *pdev)
3873{
3874 struct nct6775_data *data = platform_get_drvdata(pdev);
3875
3876 hwmon_device_unregister(data->hwmon_dev);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003877
3878 return 0;
3879}
3880
Guenter Roeck84d19d92012-12-04 08:01:39 -08003881#ifdef CONFIG_PM
3882static int nct6775_suspend(struct device *dev)
3883{
3884 struct nct6775_data *data = nct6775_update_device(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003885
3886 mutex_lock(&data->update_lock);
3887 data->vbat = nct6775_read_value(data, data->REG_VBAT);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003888 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003889 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3890 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3891 }
3892 mutex_unlock(&data->update_lock);
3893
3894 return 0;
3895}
3896
3897static int nct6775_resume(struct device *dev)
3898{
3899 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeck84d19d92012-12-04 08:01:39 -08003900 int i, j;
3901
3902 mutex_lock(&data->update_lock);
3903 data->bank = 0xff; /* Force initial bank selection */
3904
3905 /* Restore limits */
3906 for (i = 0; i < data->in_num; i++) {
3907 if (!(data->have_in & (1 << i)))
3908 continue;
3909
3910 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3911 data->in[i][1]);
3912 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3913 data->in[i][2]);
3914 }
3915
Guenter Roeckc409fd42013-04-09 05:04:00 -07003916 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003917 if (!(data->has_fan_min & (1 << i)))
3918 continue;
3919
3920 nct6775_write_value(data, data->REG_FAN_MIN[i],
3921 data->fan_min[i]);
3922 }
3923
3924 for (i = 0; i < NUM_TEMP; i++) {
3925 if (!(data->have_temp & (1 << i)))
3926 continue;
3927
Guenter Roeckc409fd42013-04-09 05:04:00 -07003928 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003929 if (data->reg_temp[j][i])
3930 nct6775_write_temp(data, data->reg_temp[j][i],
3931 data->temp[j][i]);
3932 }
3933
3934 /* Restore other settings */
3935 nct6775_write_value(data, data->REG_VBAT, data->vbat);
Guenter Roeckdf612d52013-07-08 13:15:04 -07003936 if (data->kind == nct6775) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003937 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3938 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3939 }
3940
3941 /* Force re-reading all values */
3942 data->valid = false;
3943 mutex_unlock(&data->update_lock);
3944
3945 return 0;
3946}
3947
3948static const struct dev_pm_ops nct6775_dev_pm_ops = {
3949 .suspend = nct6775_suspend,
3950 .resume = nct6775_resume,
Harald Judt374d1f92013-07-30 19:50:16 +02003951 .freeze = nct6775_suspend,
3952 .restore = nct6775_resume,
Guenter Roeck84d19d92012-12-04 08:01:39 -08003953};
3954
3955#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
3956#else
3957#define NCT6775_DEV_PM_OPS NULL
3958#endif /* CONFIG_PM */
3959
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003960static struct platform_driver nct6775_driver = {
3961 .driver = {
3962 .owner = THIS_MODULE,
3963 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08003964 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003965 },
3966 .probe = nct6775_probe,
3967 .remove = nct6775_remove,
3968};
3969
Guenter Roeck6d4b3622013-04-21 09:08:11 -07003970static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07003971 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07003972 "NCT6775F",
3973 "NCT6776D/F",
3974 "NCT6779D",
David Bartley578ab5f2013-06-24 22:28:28 -07003975 "NCT6791D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07003976};
3977
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003978/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003979static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003980{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003981 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003982 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003983 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003984
3985 err = superio_enter(sioaddr);
3986 if (err)
3987 return err;
3988
3989 if (force_id)
3990 val = force_id;
3991 else
3992 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
3993 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
3994 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003995 case SIO_NCT6106_ID:
3996 sio_data->kind = nct6106;
3997 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003998 case SIO_NCT6775_ID:
3999 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004000 break;
4001 case SIO_NCT6776_ID:
4002 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004003 break;
4004 case SIO_NCT6779_ID:
4005 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004006 break;
David Bartley578ab5f2013-06-24 22:28:28 -07004007 case SIO_NCT6791_ID:
4008 sio_data->kind = nct6791;
4009 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004010 default:
4011 if (val != 0xffff)
4012 pr_debug("unsupported chip ID: 0x%04x\n", val);
4013 superio_exit(sioaddr);
4014 return -ENODEV;
4015 }
4016
4017 /* We have a known chip, find the HWM I/O address */
4018 superio_select(sioaddr, NCT6775_LD_HWM);
4019 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
4020 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004021 addr = val & IOREGION_ALIGNMENT;
4022 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004023 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
4024 superio_exit(sioaddr);
4025 return -ENODEV;
4026 }
4027
4028 /* Activate logical device if needed */
4029 val = superio_inb(sioaddr, SIO_REG_ENABLE);
4030 if (!(val & 0x01)) {
4031 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
4032 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
4033 }
David Bartley578ab5f2013-06-24 22:28:28 -07004034 if (sio_data->kind == nct6791) {
4035 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
4036 if (val & 0x10) {
4037 pr_info("Enabling hardware monitor logical device mappings.\n");
4038 superio_outb(sioaddr,
4039 NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
4040 val & ~0x10);
4041 }
4042 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004043
4044 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07004045 pr_info("Found %s or compatible chip at %#x:%#x\n",
4046 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004047 sio_data->sioreg = sioaddr;
4048
Guenter Roeck698a7c22013-04-05 07:35:25 -07004049 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004050}
4051
4052/*
4053 * when Super-I/O functions move to a separate file, the Super-I/O
4054 * bus will manage the lifetime of the device and this module will only keep
Guenter Roeck615fc8c2013-07-06 09:43:30 -07004055 * track of the nct6775 driver. But since we use platform_device_alloc(), we
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004056 * must keep track of the device
4057 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004058static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004059
4060static int __init sensors_nct6775_init(void)
4061{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004062 int i, err;
4063 bool found = false;
4064 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004065 struct resource res;
4066 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07004067 int sioaddr[2] = { 0x2e, 0x4e };
4068
4069 err = platform_driver_register(&nct6775_driver);
4070 if (err)
4071 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004072
4073 /*
4074 * initialize sio_data->kind and sio_data->sioreg.
4075 *
4076 * when Super-I/O functions move to a separate file, the Super-I/O
4077 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
4078 * nct6775 hardware monitor, and call probe()
4079 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07004080 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4081 address = nct6775_find(sioaddr[i], &sio_data);
4082 if (address <= 0)
4083 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004084
Guenter Roeck698a7c22013-04-05 07:35:25 -07004085 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004086
Guenter Roeck698a7c22013-04-05 07:35:25 -07004087 pdev[i] = platform_device_alloc(DRVNAME, address);
4088 if (!pdev[i]) {
4089 err = -ENOMEM;
4090 goto exit_device_put;
4091 }
4092
4093 err = platform_device_add_data(pdev[i], &sio_data,
4094 sizeof(struct nct6775_sio_data));
4095 if (err)
4096 goto exit_device_put;
4097
4098 memset(&res, 0, sizeof(res));
4099 res.name = DRVNAME;
4100 res.start = address + IOREGION_OFFSET;
4101 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
4102 res.flags = IORESOURCE_IO;
4103
4104 err = acpi_check_resource_conflict(&res);
4105 if (err) {
4106 platform_device_put(pdev[i]);
4107 pdev[i] = NULL;
4108 continue;
4109 }
4110
4111 err = platform_device_add_resources(pdev[i], &res, 1);
4112 if (err)
4113 goto exit_device_put;
4114
4115 /* platform_device_add calls probe() */
4116 err = platform_device_add(pdev[i]);
4117 if (err)
4118 goto exit_device_put;
4119 }
4120 if (!found) {
4121 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004122 goto exit_unregister;
4123 }
4124
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004125 return 0;
4126
4127exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07004128 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4129 if (pdev[i])
4130 platform_device_put(pdev[i]);
4131 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004132exit_unregister:
4133 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004134 return err;
4135}
4136
4137static void __exit sensors_nct6775_exit(void)
4138{
Guenter Roeck698a7c22013-04-05 07:35:25 -07004139 int i;
4140
4141 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
4142 if (pdev[i])
4143 platform_device_unregister(pdev[i]);
4144 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07004145 platform_driver_unregister(&nct6775_driver);
4146}
4147
4148MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4149MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
4150MODULE_LICENSE("GPL");
4151
4152module_init(sensors_nct6775_init);
4153module_exit(sensors_nct6775_exit);